3 */
4
5 /*
6 * Copyright 2005 The Apache Software Foundation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 package com.sun.org.apache.xerces.internal.impl;
22
23 import java.io.EOFException;
24 import java.io.IOException;
25 import java.util.Locale;
26 import java.util.Vector;
27
28 import com.sun.xml.internal.stream.Entity;
29 import com.sun.xml.internal.stream.XMLBufferListener;
30 import java.io.InputStream;
31 import java.io.InputStreamReader;
32 import java.io.Reader;
33
34
35 import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader;
36 import com.sun.org.apache.xerces.internal.impl.io.UCSReader;
37 import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader;
38
39
40 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
41 import com.sun.org.apache.xerces.internal.util.EncodingMap;
42
43 import com.sun.org.apache.xerces.internal.util.SymbolTable;
44 import com.sun.org.apache.xerces.internal.util.XMLChar;
45 import com.sun.org.apache.xerces.internal.util.XMLStringBuffer;
46 import com.sun.org.apache.xerces.internal.xni.QName;
47 import com.sun.org.apache.xerces.internal.xni.XMLString;
48 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
49 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
50 import com.sun.org.apache.xerces.internal.xni.*;
51
52 /**
53 * Implements the entity scanner methods.
54 *
55 * @author Neeraj Bajaj, Sun Microsystems
56 * @author Andy Clark, IBM
57 * @author Arnaud Le Hors, IBM
58 * @author K.Venugopal Sun Microsystems
59 *
60 */
61 public class XMLEntityScanner implements XMLLocator {
62
63
64 protected Entity.ScannedEntity fCurrentEntity = null ;
65 protected int fBufferSize = XMLEntityManager.DEFAULT_BUFFER_SIZE;
66
67 protected XMLEntityManager fEntityManager ;
68
69 /** Debug switching readers for encodings. */
70 private static final boolean DEBUG_ENCODINGS = false;
476 }
477 }//getChar()
478
479 /**
480 * Returns the next character on the input.
481 * <p>
482 * <strong>Note:</strong> The character is <em>not</em> consumed.
483 *
484 * @throws IOException Thrown if i/o error occurs.
485 * @throws EOFException Thrown on end of file.
486 */
487 public int peekChar() throws IOException {
488 if (DEBUG_BUFFER) {
489 System.out.print("(peekChar: ");
490 print();
491 System.out.println();
492 }
493
494 // load more characters, if needed
495 if (fCurrentEntity.position == fCurrentEntity.count) {
496 invokeListeners(0);
497 load(0, true);
498 }
499
500 // peek at character
501 int c = fCurrentEntity.ch[fCurrentEntity.position];
502
503 // return peeked character
504 if (DEBUG_BUFFER) {
505 System.out.print(")peekChar: ");
506 print();
507 if (isExternal) {
508 System.out.println(" -> '"+(c!='\r'?(char)c:'\n')+"'");
509 } else {
510 System.out.println(" -> '"+(char)c+"'");
511 }
512 }
513 if (isExternal) {
514 return c != '\r' ? c : '\n';
515 } else {
516 return c;
517 }
518
519 } // peekChar():int
520
521 /**
522 * Returns the next character on the input.
523 * <p>
524 * <strong>Note:</strong> The character is consumed.
525 *
526 * @throws IOException Thrown if i/o error occurs.
527 * @throws EOFException Thrown on end of file.
528 */
529 public int scanChar() throws IOException {
530 if (DEBUG_BUFFER) {
531 System.out.print("(scanChar: ");
532 print();
533 System.out.println();
534 }
535
536 // load more characters, if needed
537 if (fCurrentEntity.position == fCurrentEntity.count) {
538 invokeListeners(0);
539 load(0, true);
540 }
541
542 // scan character
543 int c = fCurrentEntity.ch[fCurrentEntity.position++];
544 if (c == '\n' ||
545 (c == '\r' && isExternal)) {
546 fCurrentEntity.lineNumber++;
547 fCurrentEntity.columnNumber = 1;
548 if (fCurrentEntity.position == fCurrentEntity.count) {
549 invokeListeners(1);
550 fCurrentEntity.ch[0] = (char)c;
551 load(1, false);
552 }
553 if (c == '\r' && isExternal) {
554 if (fCurrentEntity.ch[fCurrentEntity.position++] != '\n') {
555 fCurrentEntity.position--;
556 }
557 c = '\n';
558 }
559 }
560
561 // return character that was scanned
562 if (DEBUG_BUFFER) {
563 System.out.print(")scanChar: ");
564 print();
565 System.out.println(" -> '"+(char)c+"'");
566 }
567 fCurrentEntity.columnNumber++;
568 return c;
569
570 } // scanChar():int
571
576 * <strong>Note:</strong> The NMTOKEN characters are consumed.
577 * <p>
578 * <strong>Note:</strong> The string returned must be a symbol. The
579 * SymbolTable can be used for this purpose.
580 *
581 * @throws IOException Thrown if i/o error occurs.
582 * @throws EOFException Thrown on end of file.
583 *
584 * @see com.sun.org.apache.xerces.internal.util.SymbolTable
585 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
586 */
587 public String scanNmtoken() throws IOException {
588 if (DEBUG_BUFFER) {
589 System.out.print("(scanNmtoken: ");
590 print();
591 System.out.println();
592 }
593
594 // load more characters, if needed
595 if (fCurrentEntity.position == fCurrentEntity.count) {
596 invokeListeners(0);
597 load(0, true);
598 }
599
600 // scan nmtoken
601 int offset = fCurrentEntity.position;
602 boolean vc = false;
603 char c;
604 while (true){
605 //while (XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) {
606 c = fCurrentEntity.ch[fCurrentEntity.position];
607 if(c < 127){
608 vc = VALID_NAMES[c];
609 }else{
610 vc = XMLChar.isName(c);
611 }
612 if(!vc)break;
613
614 if (++fCurrentEntity.position == fCurrentEntity.count) {
615 int length = fCurrentEntity.position - offset;
616 invokeListeners(length);
617 if (length == fCurrentEntity.fBufferSize) {
618 // bad luck we have to resize our buffer
619 char[] tmp = new char[fCurrentEntity.fBufferSize * 2];
620 System.arraycopy(fCurrentEntity.ch, offset,
621 tmp, 0, length);
622 fCurrentEntity.ch = tmp;
623 fCurrentEntity.fBufferSize *= 2;
624 } else {
625 System.arraycopy(fCurrentEntity.ch, offset,
626 fCurrentEntity.ch, 0, length);
627 }
628 offset = 0;
629 if (load(length, false)) {
630 break;
631 }
632 }
633 }
634 int length = fCurrentEntity.position - offset;
635 fCurrentEntity.columnNumber += length;
636
637 // return nmtoken
638 String symbol = null;
639 if (length > 0) {
640 symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
641 }
642 if (DEBUG_BUFFER) {
643 System.out.print(")scanNmtoken: ");
644 print();
645 System.out.println(" -> "+String.valueOf(symbol));
646 }
647 return symbol;
648
649 } // scanNmtoken():String
656 * <p>
657 * <strong>Note:</strong> The string returned must be a symbol. The
658 * SymbolTable can be used for this purpose.
659 *
660 * @throws IOException Thrown if i/o error occurs.
661 * @throws EOFException Thrown on end of file.
662 *
663 * @see com.sun.org.apache.xerces.internal.util.SymbolTable
664 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
665 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart
666 */
667 public String scanName() throws IOException {
668 if (DEBUG_BUFFER) {
669 System.out.print("(scanName: ");
670 print();
671 System.out.println();
672 }
673
674 // load more characters, if needed
675 if (fCurrentEntity.position == fCurrentEntity.count) {
676 invokeListeners(0);
677 load(0, true);
678 }
679
680 // scan name
681 int offset = fCurrentEntity.position;
682 if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) {
683 if (++fCurrentEntity.position == fCurrentEntity.count) {
684 invokeListeners(1);
685 fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
686 offset = 0;
687 if (load(1, false)) {
688 fCurrentEntity.columnNumber++;
689 String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
690
691 if (DEBUG_BUFFER) {
692 System.out.print(")scanName: ");
693 print();
694 System.out.println(" -> "+String.valueOf(symbol));
695 }
696 return symbol;
697 }
698 }
699 boolean vc =false;
700 while (true ){
701 //XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) ;
702 char c = fCurrentEntity.ch[fCurrentEntity.position];
703 if(c < 127){
704 vc = VALID_NAMES[c];
705 }else{
706 vc = XMLChar.isName(c);
707 }
708 if(!vc)break;
709 if (++fCurrentEntity.position == fCurrentEntity.count) {
710 int length = fCurrentEntity.position - offset;
711 invokeListeners(length);
712 if (length == fCurrentEntity.fBufferSize) {
713 // bad luck we have to resize our buffer
714 char[] tmp = new char[fCurrentEntity.fBufferSize * 2];
715 System.arraycopy(fCurrentEntity.ch, offset,
716 tmp, 0, length);
717 fCurrentEntity.ch = tmp;
718 fCurrentEntity.fBufferSize *= 2;
719 } else {
720 System.arraycopy(fCurrentEntity.ch, offset,
721 fCurrentEntity.ch, 0, length);
722 }
723 offset = 0;
724 if (load(length, false)) {
725 break;
726 }
727 }
728 }
729 }
730 int length = fCurrentEntity.position - offset;
731 fCurrentEntity.columnNumber += length;
732
733 // return name
734 String symbol;
735 if (length > 0) {
736 symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
737 } else
738 symbol = null;
739 if (DEBUG_BUFFER) {
740 System.out.print(")scanName: ");
741 print();
742 System.out.println(" -> "+String.valueOf(symbol));
743 }
744 return symbol;
759 *
760 * @return Returns true if a qualified name appeared immediately on
761 * the input and was scanned, false otherwise.
762 *
763 * @throws IOException Thrown if i/o error occurs.
764 * @throws EOFException Thrown on end of file.
765 *
766 * @see com.sun.org.apache.xerces.internal.util.SymbolTable
767 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
768 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart
769 */
770 public boolean scanQName(QName qname) throws IOException {
771 if (DEBUG_BUFFER) {
772 System.out.print("(scanQName, "+qname+": ");
773 print();
774 System.out.println();
775 }
776
777 // load more characters, if needed
778 if (fCurrentEntity.position == fCurrentEntity.count) {
779 invokeListeners(0);
780 load(0, true);
781 }
782
783 // scan qualified name
784 int offset = fCurrentEntity.position;
785
786 //making a check if if the specified character is a valid name start character
787 //as defined by production [5] in the XML 1.0 specification.
788 // Name ::= (Letter | '_' | ':') (NameChar)*
789
790 if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) {
791 if (++fCurrentEntity.position == fCurrentEntity.count) {
792 invokeListeners(1);
793 fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
794 offset = 0;
795
796 if (load(1, false)) {
797 fCurrentEntity.columnNumber++;
798 //adding into symbol table.
799 //XXX We are trying to add single character in SymbolTable??????
800 String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
801 qname.setValues(null, name, name, null);
802 if (DEBUG_BUFFER) {
803 System.out.print(")scanQName, "+qname+": ");
804 print();
805 System.out.println(" -> true");
806 }
807 return true;
808 }
809 }
810 int index = -1;
811 boolean vc = false;
812 while ( true){
813
814 //XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) ;
815 char c = fCurrentEntity.ch[fCurrentEntity.position];
816 if(c < 127){
826 index = fCurrentEntity.position;
827 }
828 if (++fCurrentEntity.position == fCurrentEntity.count) {
829 int length = fCurrentEntity.position - offset;
830 invokeListeners(length);
831 if (length == fCurrentEntity.fBufferSize) {
832 // bad luck we have to resize our buffer
833 char[] tmp = new char[fCurrentEntity.fBufferSize * 2];
834 System.arraycopy(fCurrentEntity.ch, offset,
835 tmp, 0, length);
836 fCurrentEntity.ch = tmp;
837 fCurrentEntity.fBufferSize *= 2;
838 } else {
839 System.arraycopy(fCurrentEntity.ch, offset,
840 fCurrentEntity.ch, 0, length);
841 }
842 if (index != -1) {
843 index = index - offset;
844 }
845 offset = 0;
846 if (load(length, false)) {
847 break;
848 }
849 }
850 }
851 int length = fCurrentEntity.position - offset;
852 fCurrentEntity.columnNumber += length;
853 if (length > 0) {
854 String prefix = null;
855 String localpart = null;
856 String rawname = fSymbolTable.addSymbol(fCurrentEntity.ch,
857 offset, length);
858
859 if (index != -1) {
860 int prefixLength = index - offset;
861 prefix = fSymbolTable.addSymbol(fCurrentEntity.ch,
862 offset, prefixLength);
863 int len = length - prefixLength - 1;
864 localpart = fSymbolTable.addSymbol(fCurrentEntity.ch,
865 index + 1, len);
866
901 * <p>
902 *
903 * @param content The content structure to fill.
904 *
905 * @return Returns the next character on the input, if known. This
906 * value may be -1 but this does <em>note</em> designate
907 * end of file.
908 *
909 * @throws IOException Thrown if i/o error occurs.
910 * @throws EOFException Thrown on end of file.
911 */
912 public int scanContent(XMLString content) throws IOException {
913 if (DEBUG_BUFFER) {
914 System.out.print("(scanContent: ");
915 print();
916 System.out.println();
917 }
918
919 // load more characters, if needed
920 if (fCurrentEntity.position == fCurrentEntity.count) {
921 invokeListeners(0);
922 load(0, true);
923 } else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
924 invokeListeners(0);
925 fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
926 load(1, false);
927 fCurrentEntity.position = 0;
928 }
929
930 // normalize newlines
931 int offset = fCurrentEntity.position;
932 int c = fCurrentEntity.ch[offset];
933 int newlines = 0;
934 if (c == '\n' || (c == '\r' && isExternal)) {
935 if (DEBUG_BUFFER) {
936 System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
937 print();
938 System.out.println();
939 }
940 do {
941 c = fCurrentEntity.ch[fCurrentEntity.position++];
942 if (c == '\r' && isExternal) {
943 newlines++;
944 fCurrentEntity.lineNumber++;
945 fCurrentEntity.columnNumber = 1;
946 if (fCurrentEntity.position == fCurrentEntity.count) {
947 offset = 0;
948 invokeListeners(newlines);
949 fCurrentEntity.position = newlines;
950 if (load(newlines, false)) {
951 break;
952 }
953 }
954 if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
955 fCurrentEntity.position++;
956 offset++;
957 }
958 /*** NEWLINE NORMALIZATION ***/
959 else {
960 newlines++;
961 }
962 } else if (c == '\n') {
963 newlines++;
964 fCurrentEntity.lineNumber++;
965 fCurrentEntity.columnNumber = 1;
966 if (fCurrentEntity.position == fCurrentEntity.count) {
967 offset = 0;
968 invokeListeners(newlines);
969 fCurrentEntity.position = newlines;
970 if (load(newlines, false)) {
971 break;
972 }
973 }
974 } else {
975 fCurrentEntity.position--;
976 break;
977 }
978 } while (fCurrentEntity.position < fCurrentEntity.count - 1);
979 for (int i = offset; i < fCurrentEntity.position; i++) {
980 fCurrentEntity.ch[i] = '\n';
981 }
982 int length = fCurrentEntity.position - offset;
983 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
984 //CHANGED: dont replace the value.. append to the buffer. This gives control to the callee
985 //on buffering the data..
986 content.setValues(fCurrentEntity.ch, offset, length);
987 //content.append(fCurrentEntity.ch, offset, length);
988 if (DEBUG_BUFFER) {
989 System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
990 print();
1053 * @param quote The quote character that signifies the end of the
1054 * attribute value data.
1055 * @param content The content structure to fill.
1056 *
1057 * @return Returns the next character on the input, if known. This
1058 * value may be -1 but this does <em>note</em> designate
1059 * end of file.
1060 *
1061 * @throws IOException Thrown if i/o error occurs.
1062 * @throws EOFException Thrown on end of file.
1063 */
1064 public int scanLiteral(int quote, XMLString content)
1065 throws IOException {
1066 if (DEBUG_BUFFER) {
1067 System.out.print("(scanLiteral, '"+(char)quote+"': ");
1068 print();
1069 System.out.println();
1070 }
1071 // load more characters, if needed
1072 if (fCurrentEntity.position == fCurrentEntity.count) {
1073 invokeListeners(0);
1074 load(0, true);
1075 } else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1076 invokeListeners(0);
1077 fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
1078
1079 load(1, false);
1080 fCurrentEntity.position = 0;
1081 }
1082
1083 // normalize newlines
1084 int offset = fCurrentEntity.position;
1085 int c = fCurrentEntity.ch[offset];
1086 int newlines = 0;
1087 if(whiteSpaceInfoNeeded)
1088 whiteSpaceLen=0;
1089 if (c == '\n' || (c == '\r' && isExternal)) {
1090 if (DEBUG_BUFFER) {
1091 System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
1092 print();
1093 System.out.println();
1094 }
1095 do {
1096 c = fCurrentEntity.ch[fCurrentEntity.position++];
1097 if (c == '\r' && isExternal) {
1098 newlines++;
1099 fCurrentEntity.lineNumber++;
1100 fCurrentEntity.columnNumber = 1;
1101 if (fCurrentEntity.position == fCurrentEntity.count) {
1102 invokeListeners(newlines);
1103 offset = 0;
1104 fCurrentEntity.position = newlines;
1105 if (load(newlines, false)) {
1106 break;
1107 }
1108 }
1109 if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
1110 fCurrentEntity.position++;
1111 offset++;
1112 }
1113 /*** NEWLINE NORMALIZATION ***/
1114 else {
1115 newlines++;
1116 }
1117 /***/
1118 } else if (c == '\n') {
1119 newlines++;
1120 fCurrentEntity.lineNumber++;
1121 fCurrentEntity.columnNumber = 1;
1122 if (fCurrentEntity.position == fCurrentEntity.count) {
1123 offset = 0;
1124 invokeListeners(newlines);
1125 fCurrentEntity.position = newlines;
1126 if (load(newlines, false)) {
1127 break;
1128 }
1129 }
1130 /*** NEWLINE NORMALIZATION ***
1131 * if (fCurrentEntity.ch[fCurrentEntity.position] == '\r'
1132 * && external) {
1133 * fCurrentEntity.position++;
1134 * offset++;
1135 * }
1136 * /***/
1137 } else {
1138 fCurrentEntity.position--;
1139 break;
1140 }
1141 } while (fCurrentEntity.position < fCurrentEntity.count - 1);
1142 int i=0;
1143 for ( i = offset; i < fCurrentEntity.position; i++) {
1144 fCurrentEntity.ch[i] = '\n';
1145 storeWhiteSpace(i);
1146 }
1157 }
1158 if (DEBUG_BUFFER) {
1159 System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
1160 print();
1161 System.out.println();
1162 }
1163 }
1164
1165 // scan literal value
1166 for (; fCurrentEntity.position<fCurrentEntity.count; fCurrentEntity.position++) {
1167 c = fCurrentEntity.ch[fCurrentEntity.position];
1168 if ((c == quote &&
1169 (!fCurrentEntity.literal || isExternal)) ||
1170 c == '%' || !XMLChar.isContent(c)) {
1171 break;
1172 }
1173 if (whiteSpaceInfoNeeded && c == '\t') {
1174 storeWhiteSpace(fCurrentEntity.position);
1175 }
1176 }
1177
1178 int length = fCurrentEntity.position - offset;
1179 fCurrentEntity.columnNumber += length - newlines;
1180 content.setValues(fCurrentEntity.ch, offset, length);
1181
1182 // return next character
1183 if (fCurrentEntity.position != fCurrentEntity.count) {
1184 c = fCurrentEntity.ch[fCurrentEntity.position];
1185 // NOTE: We don't want to accidentally signal the
1186 // end of the literal if we're expanding an
1187 // entity appearing in the literal. -Ac
1188 if (c == quote && fCurrentEntity.literal) {
1189 c = -1;
1190 }
1191 } else {
1192 c = -1;
1193 }
1194 if (DEBUG_BUFFER) {
1195 System.out.print(")scanLiteral, '"+(char)quote+"': ");
1196 print();
1197 System.out.println(" -> '"+(char)c+"'");
1241 *
1242 * @throws IOException Thrown if i/o error occurs.
1243 * @throws EOFException Thrown on end of file.
1244 */
1245 public boolean scanData(String delimiter, XMLStringBuffer buffer)
1246 throws IOException {
1247
1248 boolean done = false;
1249 int delimLen = delimiter.length();
1250 char charAt0 = delimiter.charAt(0);
1251 do {
1252 if (DEBUG_BUFFER) {
1253 System.out.print("(scanData: ");
1254 print();
1255 System.out.println();
1256 }
1257
1258 // load more characters, if needed
1259
1260 if (fCurrentEntity.position == fCurrentEntity.count) {
1261 load(0, true);
1262 }
1263
1264 boolean bNextEntity = false;
1265
1266 while ((fCurrentEntity.position > fCurrentEntity.count - delimLen)
1267 && (!bNextEntity))
1268 {
1269 System.arraycopy(fCurrentEntity.ch,
1270 fCurrentEntity.position,
1271 fCurrentEntity.ch,
1272 0,
1273 fCurrentEntity.count - fCurrentEntity.position);
1274
1275 bNextEntity = load(fCurrentEntity.count - fCurrentEntity.position, false);
1276 fCurrentEntity.position = 0;
1277 fCurrentEntity.startPosition = 0;
1278 }
1279
1280 if (fCurrentEntity.position > fCurrentEntity.count - delimLen) {
1281 // something must be wrong with the input: e.g., file ends in an unterminated comment
1282 int length = fCurrentEntity.count - fCurrentEntity.position;
1283 buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length);
1284 fCurrentEntity.columnNumber += fCurrentEntity.count;
1285 fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1286 fCurrentEntity.position = fCurrentEntity.count;
1287 fCurrentEntity.startPosition = fCurrentEntity.count;
1288 load(0, true);
1289 return false;
1290 }
1291
1292 // normalize newlines
1293 int offset = fCurrentEntity.position;
1294 int c = fCurrentEntity.ch[offset];
1295 int newlines = 0;
1296 if (c == '\n' || (c == '\r' && isExternal)) {
1297 if (DEBUG_BUFFER) {
1298 System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
1299 print();
1300 System.out.println();
1301 }
1302 do {
1303 c = fCurrentEntity.ch[fCurrentEntity.position++];
1304 if (c == '\r' && isExternal) {
1305 newlines++;
1306 fCurrentEntity.lineNumber++;
1307 fCurrentEntity.columnNumber = 1;
1308 if (fCurrentEntity.position == fCurrentEntity.count) {
1309 offset = 0;
1310 invokeListeners(newlines);
1311 fCurrentEntity.position = newlines;
1312 if (load(newlines, false)) {
1313 break;
1314 }
1315 }
1316 if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
1317 fCurrentEntity.position++;
1318 offset++;
1319 }
1320 /*** NEWLINE NORMALIZATION ***/
1321 else {
1322 newlines++;
1323 }
1324 } else if (c == '\n') {
1325 newlines++;
1326 fCurrentEntity.lineNumber++;
1327 fCurrentEntity.columnNumber = 1;
1328 if (fCurrentEntity.position == fCurrentEntity.count) {
1329 offset = 0;
1330 invokeListeners(newlines);
1331 fCurrentEntity.position = newlines;
1332 fCurrentEntity.count = newlines;
1333 if (load(newlines, false)) {
1334 break;
1335 }
1336 }
1337 } else {
1338 fCurrentEntity.position--;
1339 break;
1340 }
1341 } while (fCurrentEntity.position < fCurrentEntity.count - 1);
1342 for (int i = offset; i < fCurrentEntity.position; i++) {
1343 fCurrentEntity.ch[i] = '\n';
1344 }
1345 int length = fCurrentEntity.position - offset;
1346 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1347 buffer.append(fCurrentEntity.ch, offset, length);
1348 if (DEBUG_BUFFER) {
1349 System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
1350 print();
1351 System.out.println();
1352 }
1353 return true;
1414 * <p>
1415 * <strong>Note:</strong> The character is consumed only if it matches
1416 * the specified character.
1417 *
1418 * @param c The character to skip.
1419 *
1420 * @return Returns true if the character was skipped.
1421 *
1422 * @throws IOException Thrown if i/o error occurs.
1423 * @throws EOFException Thrown on end of file.
1424 */
1425 public boolean skipChar(int c) throws IOException {
1426 if (DEBUG_BUFFER) {
1427 System.out.print("(skipChar, '"+(char)c+"': ");
1428 print();
1429 System.out.println();
1430 }
1431
1432 // load more characters, if needed
1433 if (fCurrentEntity.position == fCurrentEntity.count) {
1434 invokeListeners(0);
1435 load(0, true);
1436 }
1437
1438 // skip character
1439 int cc = fCurrentEntity.ch[fCurrentEntity.position];
1440 if (cc == c) {
1441 fCurrentEntity.position++;
1442 if (c == '\n') {
1443 fCurrentEntity.lineNumber++;
1444 fCurrentEntity.columnNumber = 1;
1445 } else {
1446 fCurrentEntity.columnNumber++;
1447 }
1448 if (DEBUG_BUFFER) {
1449 System.out.print(")skipChar, '"+(char)c+"': ");
1450 print();
1451 System.out.println(" -> true");
1452 }
1453 return true;
1454 } else if (c == '\n' && cc == '\r' && isExternal) {
1455 // handle newlines
1456 if (fCurrentEntity.position == fCurrentEntity.count) {
1457 invokeListeners(1);
1458 fCurrentEntity.ch[0] = (char)cc;
1459 load(1, false);
1460 }
1461 fCurrentEntity.position++;
1462 if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
1463 fCurrentEntity.position++;
1464 }
1465 fCurrentEntity.lineNumber++;
1466 fCurrentEntity.columnNumber = 1;
1467 if (DEBUG_BUFFER) {
1468 System.out.print(")skipChar, '"+(char)c+"': ");
1469 print();
1470 System.out.println(" -> true");
1471 }
1472 return true;
1473 }
1474
1475 // character was not skipped
1476 if (DEBUG_BUFFER) {
1477 System.out.print(")skipChar, '"+(char)c+"': ");
1478 print();
1479 System.out.println(" -> false");
1490 * <p>
1491 * <strong>Note:</strong> The characters are consumed only if they are
1492 * space characters.
1493 *
1494 * @return Returns true if at least one space character was skipped.
1495 *
1496 * @throws IOException Thrown if i/o error occurs.
1497 * @throws EOFException Thrown on end of file.
1498 *
1499 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
1500 */
1501 public boolean skipSpaces() throws IOException {
1502 if (DEBUG_BUFFER) {
1503 System.out.print("(skipSpaces: ");
1504 print();
1505 System.out.println();
1506 }
1507 //boolean entityChanged = false;
1508 // load more characters, if needed
1509 if (fCurrentEntity.position == fCurrentEntity.count) {
1510 invokeListeners(0);
1511 load(0, true);
1512 }
1513
1514 //we are doing this check only in skipSpace() because it is called by
1515 //fMiscDispatcher and we want the parser to exit gracefully when document
1516 //is well-formed.
1517 //it is possible that end of document is reached and
1518 //fCurrentEntity becomes null
1519 //nothing was read so entity changed 'false' should be returned.
1520 if(fCurrentEntity == null){
1521 return false ;
1522 }
1523
1524 // skip spaces
1525 int c = fCurrentEntity.ch[fCurrentEntity.position];
1526 if (XMLChar.isSpace(c)) {
1527 do {
1528 boolean entityChanged = false;
1529 // handle newlines
1530 if (c == '\n' || (isExternal && c == '\r')) {
1531 fCurrentEntity.lineNumber++;
1532 fCurrentEntity.columnNumber = 1;
1533 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1534 invokeListeners(0);
1535 fCurrentEntity.ch[0] = (char)c;
1536 entityChanged = load(1, true);
1537 if (!entityChanged){
1538 // the load change the position to be 1,
1539 // need to restore it when entity not changed
1540 fCurrentEntity.position = 0;
1541 }else if(fCurrentEntity == null){
1542 return true ;
1543 }
1544 }
1545 if (c == '\r' && isExternal) {
1546 // REVISIT: Does this need to be updated to fix the
1547 // #x0D ^#x0A newline normalization problem? -Ac
1548 if (fCurrentEntity.ch[++fCurrentEntity.position] != '\n') {
1549 fCurrentEntity.position--;
1550 }
1551 }
1552 } else {
1553 fCurrentEntity.columnNumber++;
1554 }
1555 // load more characters, if needed
1556 if (!entityChanged){
1557 fCurrentEntity.position++;
1558 }
1559
1560 if (fCurrentEntity.position == fCurrentEntity.count) {
1561 invokeListeners(0);
1562 load(0, true);
1563
1564 //we are doing this check only in skipSpace() because it is called by
1565 //fMiscDispatcher and we want the parser to exit gracefully when document
1566 //is well-formed.
1567
1568 //it is possible that end of document is reached and
1569 //fCurrentEntity becomes null
1570 //nothing was read so entity changed 'false' should be returned.
1571 if(fCurrentEntity == null){
1572 return true ;
1573 }
1574
1575 }
1576 } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
1577 if (DEBUG_BUFFER) {
1578 System.out.print(")skipSpaces: ");
1579 print();
1580 System.out.println(" -> true");
1581 }
1582 return true;
1618 return true;
1619 }
1620 if(DEBUG_SKIP_STRING){
1621 System.out.println("fCurrentEntity.count = " + fCurrentEntity.count);
1622 System.out.println("fCurrentEntity.position = " + fCurrentEntity.position);
1623 System.out.println("length = " + length);
1624 }
1625 boolean entityChanged = false;
1626 //load more characters -- this function shouldn't change the entity
1627 while((fCurrentEntity.count - fCurrentEntity.position) < length){
1628 if( (fCurrentEntity.ch.length - fCurrentEntity.position) < length){
1629 invokeListeners(0);
1630 System.arraycopy(fCurrentEntity.ch, fCurrentEntity.position, fCurrentEntity.ch,0,fCurrentEntity.count - fCurrentEntity.position);
1631 fCurrentEntity.count = fCurrentEntity.count - fCurrentEntity.position;
1632 fCurrentEntity.position = 0;
1633 }
1634
1635 if((fCurrentEntity.count - fCurrentEntity.position) < length){
1636 int pos = fCurrentEntity.position;
1637 invokeListeners(pos);
1638 entityChanged = load(fCurrentEntity.count, changeEntity);
1639 fCurrentEntity.position = pos;
1640 if(entityChanged)break;
1641 }
1642 if(DEBUG_SKIP_STRING){
1643 System.out.println("fCurrentEntity.count = " + fCurrentEntity.count);
1644 System.out.println("fCurrentEntity.position = " + fCurrentEntity.position);
1645 System.out.println("length = " + length);
1646 }
1647 }
1648 //load changes the position.. set it back to the point where we started.
1649
1650 //after loading check again.
1651 if((fCurrentEntity.count - fCurrentEntity.position) >= length) {
1652 return true;
1653 } else {
1654 return false;
1655 }
1656 }
1657
1658 /**
1723 return false;
1724 }
1725
1726 //
1727 // Locator methods
1728 //
1729 //
1730 // Private methods
1731 //
1732
1733 /**
1734 * Loads a chunk of text.
1735 *
1736 * @param offset The offset into the character buffer to
1737 * read the next batch of characters.
1738 * @param changeEntity True if the load should change entities
1739 * at the end of the entity, otherwise leave
1740 * the current entity in place and the entity
1741 * boundary will be signaled by the return
1742 * value.
1743 *
1744 * @returns Returns true if the entity changed as a result of this
1745 * load operation.
1746 */
1747 final boolean load(int offset, boolean changeEntity)
1748 throws IOException {
1749 if (DEBUG_BUFFER) {
1750 System.out.print("(load, "+offset+": ");
1751 print();
1752 System.out.println();
1753 }
1754 //maintaing the count till last load
1755 fCurrentEntity.fTotalCountTillLastLoad = fCurrentEntity.fTotalCountTillLastLoad + fCurrentEntity.fLastCount ;
1756 // read characters
1757 int length = fCurrentEntity.ch.length - offset;
1758 if (!fCurrentEntity.mayReadChunks && length > XMLEntityManager.DEFAULT_XMLDECL_BUFFER_SIZE) {
1759 length = XMLEntityManager.DEFAULT_XMLDECL_BUFFER_SIZE;
1760 }
1761 if (DEBUG_BUFFER) System.out.println(" length to try to read: "+length);
1762 int count = fCurrentEntity.reader.read(fCurrentEntity.ch, offset, length);
1763 if (DEBUG_BUFFER) System.out.println(" length actually read: "+count);
1764
1765 // reset count and position
1766 boolean entityChanged = false;
1767 if (count != -1) {
1768 if (count != 0) {
1769 // record the last count
1770 fCurrentEntity.fLastCount = count;
1771 fCurrentEntity.count = count + offset;
1772 fCurrentEntity.position = offset;
1773 }
1774 }
1775 // end of this entity
1776 else {
1777 fCurrentEntity.count = offset;
1778 fCurrentEntity.position = offset;
1779 entityChanged = true;
1780
1781 if (changeEntity) {
1782 //notify the entity manager about the end of entity
1783 fEntityManager.endEntity();
1784 //return if the current entity becomes null
1785 if(fCurrentEntity == null){
1786 throw END_OF_DOCUMENT_ENTITY;
1787 }
1788 // handle the trailing edges
1789 if (fCurrentEntity.position == fCurrentEntity.count) {
1790 load(0, true);
1791 }
1792 }
1793
1794 }
1795 if (DEBUG_BUFFER) {
1796 System.out.print(")load, "+offset+": ");
1797 print();
1798 System.out.println();
1799 }
1800
1801 return entityChanged;
1802
1803 } // load(int, boolean):boolean
1804
1805 /**
1806 * Creates a reader capable of reading the given input stream in
1807 * the specified encoding.
1808 *
1809 * @param inputStream The input stream.
1810 * @param encoding The encoding name that the input stream is
2067 } else {
2068 System.out.print("*NO CURRENT ENTITY*");
2069 }
2070 }
2071 }
2072
2073 /**
2074 * Registers the listener object and provides callback.
2075 * @param listener listener to which call back should be provided when scanner buffer
2076 * is being changed.
2077 */
2078 public void registerListener(XMLBufferListener listener) {
2079 if(!listeners.contains(listener))
2080 listeners.add(listener);
2081 }
2082
2083 /**
2084 *
2085 * @param loadPos Starting position from which new data is being loaded into scanner buffer.
2086 */
2087 private void invokeListeners(int loadPos){
2088 for(int i=0;i<listeners.size();i++){
2089 XMLBufferListener listener =(XMLBufferListener) listeners.get(i);
2090 listener.refresh(loadPos);
2091 }
2092 }
2093
2094 /**
2095 * Skips space characters appearing immediately on the input that would
2096 * match non-terminal S (0x09, 0x0A, 0x0D, 0x20) before end of line
2097 * normalization is performed. This is useful when scanning structures
2098 * such as the XMLDecl and TextDecl that can only contain US-ASCII
2099 * characters.
2100 * <p>
2101 * <strong>Note:</strong> The characters are consumed only if they would
2102 * match non-terminal S before end of line normalization is performed.
2103 *
2104 * @return Returns true if at least one space character was skipped.
2105 *
2106 * @throws IOException Thrown if i/o error occurs.
2107 * @throws EOFException Thrown on end of file.
2108 *
2109 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
2110 */
2111 public final boolean skipDeclSpaces() throws IOException {
2112 if (DEBUG_BUFFER) {
2113 System.out.print("(skipDeclSpaces: ");
2114 //XMLEntityManager.print(fCurrentEntity);
2115 System.out.println();
2116 }
2117
2118 // load more characters, if needed
2119 if (fCurrentEntity.position == fCurrentEntity.count) {
2120 load(0, true);
2121 }
2122
2123 // skip spaces
2124 int c = fCurrentEntity.ch[fCurrentEntity.position];
2125 if (XMLChar.isSpace(c)) {
2126 boolean external = fCurrentEntity.isExternal();
2127 do {
2128 boolean entityChanged = false;
2129 // handle newlines
2130 if (c == '\n' || (external && c == '\r')) {
2131 fCurrentEntity.lineNumber++;
2132 fCurrentEntity.columnNumber = 1;
2133 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
2134 fCurrentEntity.ch[0] = (char)c;
2135 entityChanged = load(1, true);
2136 if (!entityChanged)
2137 // the load change the position to be 1,
2138 // need to restore it when entity not changed
2139 fCurrentEntity.position = 0;
2140 }
2141 if (c == '\r' && external) {
2142 // REVISIT: Does this need to be updated to fix the
2143 // #x0D ^#x0A newline normalization problem? -Ac
2144 if (fCurrentEntity.ch[++fCurrentEntity.position] != '\n') {
2145 fCurrentEntity.position--;
2146 }
2147 }
2148 /*** NEWLINE NORMALIZATION ***
2149 * else {
2150 * if (fCurrentEntity.ch[fCurrentEntity.position + 1] == '\r'
2151 * && external) {
2152 * fCurrentEntity.position++;
2153 * }
2154 * }
2155 * /***/
2156 } else {
2157 fCurrentEntity.columnNumber++;
2158 }
2159 // load more characters, if needed
2160 if (!entityChanged)
2161 fCurrentEntity.position++;
2162 if (fCurrentEntity.position == fCurrentEntity.count) {
2163 load(0, true);
2164 }
2165 } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
2166 if (DEBUG_BUFFER) {
2167 System.out.print(")skipDeclSpaces: ");
2168 // XMLEntityManager.print(fCurrentEntity);
2169 System.out.println(" -> true");
2170 }
2171 return true;
2172 }
2173
2174 // no spaces were found
2175 if (DEBUG_BUFFER) {
2176 System.out.print(")skipDeclSpaces: ");
2177 //XMLEntityManager.print(fCurrentEntity);
2178 System.out.println(" -> false");
2179 }
2180 return false;
2181
2182 } // skipDeclSpaces():boolean
2183
|
3 */
4
5 /*
6 * Copyright 2005 The Apache Software Foundation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 package com.sun.org.apache.xerces.internal.impl;
22
23
24
25 import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader;
26 import com.sun.org.apache.xerces.internal.impl.io.UCSReader;
27 import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader;
28 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
29 import com.sun.org.apache.xerces.internal.util.EncodingMap;
30 import com.sun.org.apache.xerces.internal.util.SymbolTable;
31 import com.sun.org.apache.xerces.internal.util.XMLChar;
32 import com.sun.org.apache.xerces.internal.util.XMLStringBuffer;
33 import com.sun.org.apache.xerces.internal.xni.*;
34 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
35 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
36 import com.sun.xml.internal.stream.Entity;
37 import com.sun.xml.internal.stream.XMLBufferListener;
38 import java.io.EOFException;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.io.InputStreamReader;
42 import java.io.Reader;
43 import java.util.Locale;
44 import java.util.Vector;
45
46 /**
47 * Implements the entity scanner methods.
48 *
49 * @author Neeraj Bajaj, Sun Microsystems
50 * @author Andy Clark, IBM
51 * @author Arnaud Le Hors, IBM
52 * @author K.Venugopal Sun Microsystems
53 *
54 */
55 public class XMLEntityScanner implements XMLLocator {
56
57
58 protected Entity.ScannedEntity fCurrentEntity = null ;
59 protected int fBufferSize = XMLEntityManager.DEFAULT_BUFFER_SIZE;
60
61 protected XMLEntityManager fEntityManager ;
62
63 /** Debug switching readers for encodings. */
64 private static final boolean DEBUG_ENCODINGS = false;
470 }
471 }//getChar()
472
473 /**
474 * Returns the next character on the input.
475 * <p>
476 * <strong>Note:</strong> The character is <em>not</em> consumed.
477 *
478 * @throws IOException Thrown if i/o error occurs.
479 * @throws EOFException Thrown on end of file.
480 */
481 public int peekChar() throws IOException {
482 if (DEBUG_BUFFER) {
483 System.out.print("(peekChar: ");
484 print();
485 System.out.println();
486 }
487
488 // load more characters, if needed
489 if (fCurrentEntity.position == fCurrentEntity.count) {
490 load(0, true, true);
491 }
492
493 // peek at character
494 int c = fCurrentEntity.ch[fCurrentEntity.position];
495
496 // return peeked character
497 if (DEBUG_BUFFER) {
498 System.out.print(")peekChar: ");
499 print();
500 if (isExternal) {
501 System.out.println(" -> '"+(c!='\r'?(char)c:'\n')+"'");
502 } else {
503 System.out.println(" -> '"+(char)c+"'");
504 }
505 }
506 if (isExternal) {
507 return c != '\r' ? c : '\n';
508 } else {
509 return c;
510 }
511
512 } // peekChar():int
513
514 /**
515 * Returns the next character on the input.
516 * <p>
517 * <strong>Note:</strong> The character is consumed.
518 *
519 * @throws IOException Thrown if i/o error occurs.
520 * @throws EOFException Thrown on end of file.
521 */
522 public int scanChar() throws IOException {
523 if (DEBUG_BUFFER) {
524 System.out.print("(scanChar: ");
525 print();
526 System.out.println();
527 }
528
529 // load more characters, if needed
530 if (fCurrentEntity.position == fCurrentEntity.count) {
531 load(0, true, true);
532 }
533
534 // scan character
535 int c = fCurrentEntity.ch[fCurrentEntity.position++];
536 if (c == '\n' ||
537 (c == '\r' && isExternal)) {
538 fCurrentEntity.lineNumber++;
539 fCurrentEntity.columnNumber = 1;
540 if (fCurrentEntity.position == fCurrentEntity.count) {
541 fCurrentEntity.ch[0] = (char)c;
542 load(1, false, true);
543 }
544 if (c == '\r' && isExternal) {
545 if (fCurrentEntity.ch[fCurrentEntity.position++] != '\n') {
546 fCurrentEntity.position--;
547 }
548 c = '\n';
549 }
550 }
551
552 // return character that was scanned
553 if (DEBUG_BUFFER) {
554 System.out.print(")scanChar: ");
555 print();
556 System.out.println(" -> '"+(char)c+"'");
557 }
558 fCurrentEntity.columnNumber++;
559 return c;
560
561 } // scanChar():int
562
567 * <strong>Note:</strong> The NMTOKEN characters are consumed.
568 * <p>
569 * <strong>Note:</strong> The string returned must be a symbol. The
570 * SymbolTable can be used for this purpose.
571 *
572 * @throws IOException Thrown if i/o error occurs.
573 * @throws EOFException Thrown on end of file.
574 *
575 * @see com.sun.org.apache.xerces.internal.util.SymbolTable
576 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
577 */
578 public String scanNmtoken() throws IOException {
579 if (DEBUG_BUFFER) {
580 System.out.print("(scanNmtoken: ");
581 print();
582 System.out.println();
583 }
584
585 // load more characters, if needed
586 if (fCurrentEntity.position == fCurrentEntity.count) {
587 load(0, true, true);
588 }
589
590 // scan nmtoken
591 int offset = fCurrentEntity.position;
592 boolean vc = false;
593 char c;
594 while (true){
595 //while (XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) {
596 c = fCurrentEntity.ch[fCurrentEntity.position];
597 if(c < 127){
598 vc = VALID_NAMES[c];
599 }else{
600 vc = XMLChar.isName(c);
601 }
602 if(!vc)break;
603
604 if (++fCurrentEntity.position == fCurrentEntity.count) {
605 int length = fCurrentEntity.position - offset;
606 invokeListeners(length);
607 if (length == fCurrentEntity.fBufferSize) {
608 // bad luck we have to resize our buffer
609 char[] tmp = new char[fCurrentEntity.fBufferSize * 2];
610 System.arraycopy(fCurrentEntity.ch, offset,
611 tmp, 0, length);
612 fCurrentEntity.ch = tmp;
613 fCurrentEntity.fBufferSize *= 2;
614 } else {
615 System.arraycopy(fCurrentEntity.ch, offset,
616 fCurrentEntity.ch, 0, length);
617 }
618 offset = 0;
619 if (load(length, false, false)) {
620 break;
621 }
622 }
623 }
624 int length = fCurrentEntity.position - offset;
625 fCurrentEntity.columnNumber += length;
626
627 // return nmtoken
628 String symbol = null;
629 if (length > 0) {
630 symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
631 }
632 if (DEBUG_BUFFER) {
633 System.out.print(")scanNmtoken: ");
634 print();
635 System.out.println(" -> "+String.valueOf(symbol));
636 }
637 return symbol;
638
639 } // scanNmtoken():String
646 * <p>
647 * <strong>Note:</strong> The string returned must be a symbol. The
648 * SymbolTable can be used for this purpose.
649 *
650 * @throws IOException Thrown if i/o error occurs.
651 * @throws EOFException Thrown on end of file.
652 *
653 * @see com.sun.org.apache.xerces.internal.util.SymbolTable
654 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
655 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart
656 */
657 public String scanName() throws IOException {
658 if (DEBUG_BUFFER) {
659 System.out.print("(scanName: ");
660 print();
661 System.out.println();
662 }
663
664 // load more characters, if needed
665 if (fCurrentEntity.position == fCurrentEntity.count) {
666 load(0, true, true);
667 }
668
669 // scan name
670 int offset = fCurrentEntity.position;
671 if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) {
672 if (++fCurrentEntity.position == fCurrentEntity.count) {
673 fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
674 offset = 0;
675 if (load(1, false, true)) {
676 fCurrentEntity.columnNumber++;
677 String symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
678
679 if (DEBUG_BUFFER) {
680 System.out.print(")scanName: ");
681 print();
682 System.out.println(" -> "+String.valueOf(symbol));
683 }
684 return symbol;
685 }
686 }
687 boolean vc =false;
688 while (true ){
689 //XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) ;
690 char c = fCurrentEntity.ch[fCurrentEntity.position];
691 if(c < 127){
692 vc = VALID_NAMES[c];
693 }else{
694 vc = XMLChar.isName(c);
695 }
696 if(!vc)break;
697 if (++fCurrentEntity.position == fCurrentEntity.count) {
698 int length = fCurrentEntity.position - offset;
699 invokeListeners(length);
700 if (length == fCurrentEntity.fBufferSize) {
701 // bad luck we have to resize our buffer
702 char[] tmp = new char[fCurrentEntity.fBufferSize * 2];
703 System.arraycopy(fCurrentEntity.ch, offset,
704 tmp, 0, length);
705 fCurrentEntity.ch = tmp;
706 fCurrentEntity.fBufferSize *= 2;
707 } else {
708 System.arraycopy(fCurrentEntity.ch, offset,
709 fCurrentEntity.ch, 0, length);
710 }
711 offset = 0;
712 if (load(length, false, false)) {
713 break;
714 }
715 }
716 }
717 }
718 int length = fCurrentEntity.position - offset;
719 fCurrentEntity.columnNumber += length;
720
721 // return name
722 String symbol;
723 if (length > 0) {
724 symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
725 } else
726 symbol = null;
727 if (DEBUG_BUFFER) {
728 System.out.print(")scanName: ");
729 print();
730 System.out.println(" -> "+String.valueOf(symbol));
731 }
732 return symbol;
747 *
748 * @return Returns true if a qualified name appeared immediately on
749 * the input and was scanned, false otherwise.
750 *
751 * @throws IOException Thrown if i/o error occurs.
752 * @throws EOFException Thrown on end of file.
753 *
754 * @see com.sun.org.apache.xerces.internal.util.SymbolTable
755 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
756 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart
757 */
758 public boolean scanQName(QName qname) throws IOException {
759 if (DEBUG_BUFFER) {
760 System.out.print("(scanQName, "+qname+": ");
761 print();
762 System.out.println();
763 }
764
765 // load more characters, if needed
766 if (fCurrentEntity.position == fCurrentEntity.count) {
767 load(0, true, true);
768 }
769
770 // scan qualified name
771 int offset = fCurrentEntity.position;
772
773 //making a check if if the specified character is a valid name start character
774 //as defined by production [5] in the XML 1.0 specification.
775 // Name ::= (Letter | '_' | ':') (NameChar)*
776
777 if (XMLChar.isNameStart(fCurrentEntity.ch[offset])) {
778 if (++fCurrentEntity.position == fCurrentEntity.count) {
779 fCurrentEntity.ch[0] = fCurrentEntity.ch[offset];
780 offset = 0;
781
782 if (load(1, false, true)) {
783 fCurrentEntity.columnNumber++;
784 //adding into symbol table.
785 //XXX We are trying to add single character in SymbolTable??????
786 String name = fSymbolTable.addSymbol(fCurrentEntity.ch, 0, 1);
787 qname.setValues(null, name, name, null);
788 if (DEBUG_BUFFER) {
789 System.out.print(")scanQName, "+qname+": ");
790 print();
791 System.out.println(" -> true");
792 }
793 return true;
794 }
795 }
796 int index = -1;
797 boolean vc = false;
798 while ( true){
799
800 //XMLChar.isName(fCurrentEntity.ch[fCurrentEntity.position])) ;
801 char c = fCurrentEntity.ch[fCurrentEntity.position];
802 if(c < 127){
812 index = fCurrentEntity.position;
813 }
814 if (++fCurrentEntity.position == fCurrentEntity.count) {
815 int length = fCurrentEntity.position - offset;
816 invokeListeners(length);
817 if (length == fCurrentEntity.fBufferSize) {
818 // bad luck we have to resize our buffer
819 char[] tmp = new char[fCurrentEntity.fBufferSize * 2];
820 System.arraycopy(fCurrentEntity.ch, offset,
821 tmp, 0, length);
822 fCurrentEntity.ch = tmp;
823 fCurrentEntity.fBufferSize *= 2;
824 } else {
825 System.arraycopy(fCurrentEntity.ch, offset,
826 fCurrentEntity.ch, 0, length);
827 }
828 if (index != -1) {
829 index = index - offset;
830 }
831 offset = 0;
832 if (load(length, false, false)) {
833 break;
834 }
835 }
836 }
837 int length = fCurrentEntity.position - offset;
838 fCurrentEntity.columnNumber += length;
839 if (length > 0) {
840 String prefix = null;
841 String localpart = null;
842 String rawname = fSymbolTable.addSymbol(fCurrentEntity.ch,
843 offset, length);
844
845 if (index != -1) {
846 int prefixLength = index - offset;
847 prefix = fSymbolTable.addSymbol(fCurrentEntity.ch,
848 offset, prefixLength);
849 int len = length - prefixLength - 1;
850 localpart = fSymbolTable.addSymbol(fCurrentEntity.ch,
851 index + 1, len);
852
887 * <p>
888 *
889 * @param content The content structure to fill.
890 *
891 * @return Returns the next character on the input, if known. This
892 * value may be -1 but this does <em>note</em> designate
893 * end of file.
894 *
895 * @throws IOException Thrown if i/o error occurs.
896 * @throws EOFException Thrown on end of file.
897 */
898 public int scanContent(XMLString content) throws IOException {
899 if (DEBUG_BUFFER) {
900 System.out.print("(scanContent: ");
901 print();
902 System.out.println();
903 }
904
905 // load more characters, if needed
906 if (fCurrentEntity.position == fCurrentEntity.count) {
907 load(0, true, true);
908 } else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
909 fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
910 load(1, false, true);
911 fCurrentEntity.position = 0;
912 }
913
914 // normalize newlines
915 int offset = fCurrentEntity.position;
916 int c = fCurrentEntity.ch[offset];
917 int newlines = 0;
918 if (c == '\n' || (c == '\r' && isExternal)) {
919 if (DEBUG_BUFFER) {
920 System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
921 print();
922 System.out.println();
923 }
924 do {
925 c = fCurrentEntity.ch[fCurrentEntity.position++];
926 if (c == '\r' && isExternal) {
927 newlines++;
928 fCurrentEntity.lineNumber++;
929 fCurrentEntity.columnNumber = 1;
930 if (fCurrentEntity.position == fCurrentEntity.count) {
931 offset = 0;
932 fCurrentEntity.position = newlines;
933 if (load(newlines, false, true)) {
934 break;
935 }
936 }
937 if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
938 fCurrentEntity.position++;
939 offset++;
940 }
941 /*** NEWLINE NORMALIZATION ***/
942 else {
943 newlines++;
944 }
945 } else if (c == '\n') {
946 newlines++;
947 fCurrentEntity.lineNumber++;
948 fCurrentEntity.columnNumber = 1;
949 if (fCurrentEntity.position == fCurrentEntity.count) {
950 offset = 0;
951 fCurrentEntity.position = newlines;
952 if (load(newlines, false, true)) {
953 break;
954 }
955 }
956 } else {
957 fCurrentEntity.position--;
958 break;
959 }
960 } while (fCurrentEntity.position < fCurrentEntity.count - 1);
961 for (int i = offset; i < fCurrentEntity.position; i++) {
962 fCurrentEntity.ch[i] = '\n';
963 }
964 int length = fCurrentEntity.position - offset;
965 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
966 //CHANGED: dont replace the value.. append to the buffer. This gives control to the callee
967 //on buffering the data..
968 content.setValues(fCurrentEntity.ch, offset, length);
969 //content.append(fCurrentEntity.ch, offset, length);
970 if (DEBUG_BUFFER) {
971 System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
972 print();
1035 * @param quote The quote character that signifies the end of the
1036 * attribute value data.
1037 * @param content The content structure to fill.
1038 *
1039 * @return Returns the next character on the input, if known. This
1040 * value may be -1 but this does <em>note</em> designate
1041 * end of file.
1042 *
1043 * @throws IOException Thrown if i/o error occurs.
1044 * @throws EOFException Thrown on end of file.
1045 */
1046 public int scanLiteral(int quote, XMLString content)
1047 throws IOException {
1048 if (DEBUG_BUFFER) {
1049 System.out.print("(scanLiteral, '"+(char)quote+"': ");
1050 print();
1051 System.out.println();
1052 }
1053 // load more characters, if needed
1054 if (fCurrentEntity.position == fCurrentEntity.count) {
1055 load(0, true, true);
1056 } else if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1057 fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1];
1058 load(1, false, true);
1059 fCurrentEntity.position = 0;
1060 }
1061
1062 // normalize newlines
1063 int offset = fCurrentEntity.position;
1064 int c = fCurrentEntity.ch[offset];
1065 int newlines = 0;
1066 if(whiteSpaceInfoNeeded)
1067 whiteSpaceLen=0;
1068 if (c == '\n' || (c == '\r' && isExternal)) {
1069 if (DEBUG_BUFFER) {
1070 System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
1071 print();
1072 System.out.println();
1073 }
1074 do {
1075 c = fCurrentEntity.ch[fCurrentEntity.position++];
1076 if (c == '\r' && isExternal) {
1077 newlines++;
1078 fCurrentEntity.lineNumber++;
1079 fCurrentEntity.columnNumber = 1;
1080 if (fCurrentEntity.position == fCurrentEntity.count) {
1081 offset = 0;
1082 fCurrentEntity.position = newlines;
1083 if (load(newlines, false, true)) {
1084 break;
1085 }
1086 }
1087 if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
1088 fCurrentEntity.position++;
1089 offset++;
1090 }
1091 /*** NEWLINE NORMALIZATION ***/
1092 else {
1093 newlines++;
1094 }
1095 /***/
1096 } else if (c == '\n') {
1097 newlines++;
1098 fCurrentEntity.lineNumber++;
1099 fCurrentEntity.columnNumber = 1;
1100 if (fCurrentEntity.position == fCurrentEntity.count) {
1101 offset = 0;
1102 fCurrentEntity.position = newlines;
1103 if (load(newlines, false, true)) {
1104 break;
1105 }
1106 }
1107 /*** NEWLINE NORMALIZATION ***
1108 * if (fCurrentEntity.ch[fCurrentEntity.position] == '\r'
1109 * && external) {
1110 * fCurrentEntity.position++;
1111 * offset++;
1112 * }
1113 * /***/
1114 } else {
1115 fCurrentEntity.position--;
1116 break;
1117 }
1118 } while (fCurrentEntity.position < fCurrentEntity.count - 1);
1119 int i=0;
1120 for ( i = offset; i < fCurrentEntity.position; i++) {
1121 fCurrentEntity.ch[i] = '\n';
1122 storeWhiteSpace(i);
1123 }
1134 }
1135 if (DEBUG_BUFFER) {
1136 System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
1137 print();
1138 System.out.println();
1139 }
1140 }
1141
1142 // scan literal value
1143 for (; fCurrentEntity.position<fCurrentEntity.count; fCurrentEntity.position++) {
1144 c = fCurrentEntity.ch[fCurrentEntity.position];
1145 if ((c == quote &&
1146 (!fCurrentEntity.literal || isExternal)) ||
1147 c == '%' || !XMLChar.isContent(c)) {
1148 break;
1149 }
1150 if (whiteSpaceInfoNeeded && c == '\t') {
1151 storeWhiteSpace(fCurrentEntity.position);
1152 }
1153 }
1154 int length = fCurrentEntity.position - offset;
1155 fCurrentEntity.columnNumber += length - newlines;
1156 content.setValues(fCurrentEntity.ch, offset, length);
1157
1158 // return next character
1159 if (fCurrentEntity.position != fCurrentEntity.count) {
1160 c = fCurrentEntity.ch[fCurrentEntity.position];
1161 // NOTE: We don't want to accidentally signal the
1162 // end of the literal if we're expanding an
1163 // entity appearing in the literal. -Ac
1164 if (c == quote && fCurrentEntity.literal) {
1165 c = -1;
1166 }
1167 } else {
1168 c = -1;
1169 }
1170 if (DEBUG_BUFFER) {
1171 System.out.print(")scanLiteral, '"+(char)quote+"': ");
1172 print();
1173 System.out.println(" -> '"+(char)c+"'");
1217 *
1218 * @throws IOException Thrown if i/o error occurs.
1219 * @throws EOFException Thrown on end of file.
1220 */
1221 public boolean scanData(String delimiter, XMLStringBuffer buffer)
1222 throws IOException {
1223
1224 boolean done = false;
1225 int delimLen = delimiter.length();
1226 char charAt0 = delimiter.charAt(0);
1227 do {
1228 if (DEBUG_BUFFER) {
1229 System.out.print("(scanData: ");
1230 print();
1231 System.out.println();
1232 }
1233
1234 // load more characters, if needed
1235
1236 if (fCurrentEntity.position == fCurrentEntity.count) {
1237 load(0, true, false);
1238 }
1239
1240 boolean bNextEntity = false;
1241
1242 while ((fCurrentEntity.position > fCurrentEntity.count - delimLen)
1243 && (!bNextEntity))
1244 {
1245 System.arraycopy(fCurrentEntity.ch,
1246 fCurrentEntity.position,
1247 fCurrentEntity.ch,
1248 0,
1249 fCurrentEntity.count - fCurrentEntity.position);
1250
1251 bNextEntity = load(fCurrentEntity.count - fCurrentEntity.position, false, false);
1252 fCurrentEntity.position = 0;
1253 fCurrentEntity.startPosition = 0;
1254 }
1255
1256 if (fCurrentEntity.position > fCurrentEntity.count - delimLen) {
1257 // something must be wrong with the input: e.g., file ends in an unterminated comment
1258 int length = fCurrentEntity.count - fCurrentEntity.position;
1259 buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length);
1260 fCurrentEntity.columnNumber += fCurrentEntity.count;
1261 fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
1262 fCurrentEntity.position = fCurrentEntity.count;
1263 fCurrentEntity.startPosition = fCurrentEntity.count;
1264 load(0, true, false);
1265 return false;
1266 }
1267
1268 // normalize newlines
1269 int offset = fCurrentEntity.position;
1270 int c = fCurrentEntity.ch[offset];
1271 int newlines = 0;
1272 if (c == '\n' || (c == '\r' && isExternal)) {
1273 if (DEBUG_BUFFER) {
1274 System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
1275 print();
1276 System.out.println();
1277 }
1278 do {
1279 c = fCurrentEntity.ch[fCurrentEntity.position++];
1280 if (c == '\r' && isExternal) {
1281 newlines++;
1282 fCurrentEntity.lineNumber++;
1283 fCurrentEntity.columnNumber = 1;
1284 if (fCurrentEntity.position == fCurrentEntity.count) {
1285 offset = 0;
1286 fCurrentEntity.position = newlines;
1287 if (load(newlines, false, true)) {
1288 break;
1289 }
1290 }
1291 if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
1292 fCurrentEntity.position++;
1293 offset++;
1294 }
1295 /*** NEWLINE NORMALIZATION ***/
1296 else {
1297 newlines++;
1298 }
1299 } else if (c == '\n') {
1300 newlines++;
1301 fCurrentEntity.lineNumber++;
1302 fCurrentEntity.columnNumber = 1;
1303 if (fCurrentEntity.position == fCurrentEntity.count) {
1304 offset = 0;
1305 fCurrentEntity.position = newlines;
1306 fCurrentEntity.count = newlines;
1307 if (load(newlines, false, true)) {
1308 break;
1309 }
1310 }
1311 } else {
1312 fCurrentEntity.position--;
1313 break;
1314 }
1315 } while (fCurrentEntity.position < fCurrentEntity.count - 1);
1316 for (int i = offset; i < fCurrentEntity.position; i++) {
1317 fCurrentEntity.ch[i] = '\n';
1318 }
1319 int length = fCurrentEntity.position - offset;
1320 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1321 buffer.append(fCurrentEntity.ch, offset, length);
1322 if (DEBUG_BUFFER) {
1323 System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
1324 print();
1325 System.out.println();
1326 }
1327 return true;
1388 * <p>
1389 * <strong>Note:</strong> The character is consumed only if it matches
1390 * the specified character.
1391 *
1392 * @param c The character to skip.
1393 *
1394 * @return Returns true if the character was skipped.
1395 *
1396 * @throws IOException Thrown if i/o error occurs.
1397 * @throws EOFException Thrown on end of file.
1398 */
1399 public boolean skipChar(int c) throws IOException {
1400 if (DEBUG_BUFFER) {
1401 System.out.print("(skipChar, '"+(char)c+"': ");
1402 print();
1403 System.out.println();
1404 }
1405
1406 // load more characters, if needed
1407 if (fCurrentEntity.position == fCurrentEntity.count) {
1408 load(0, true, true);
1409 }
1410
1411 // skip character
1412 int cc = fCurrentEntity.ch[fCurrentEntity.position];
1413 if (cc == c) {
1414 fCurrentEntity.position++;
1415 if (c == '\n') {
1416 fCurrentEntity.lineNumber++;
1417 fCurrentEntity.columnNumber = 1;
1418 } else {
1419 fCurrentEntity.columnNumber++;
1420 }
1421 if (DEBUG_BUFFER) {
1422 System.out.print(")skipChar, '"+(char)c+"': ");
1423 print();
1424 System.out.println(" -> true");
1425 }
1426 return true;
1427 } else if (c == '\n' && cc == '\r' && isExternal) {
1428 // handle newlines
1429 if (fCurrentEntity.position == fCurrentEntity.count) {
1430 fCurrentEntity.ch[0] = (char)cc;
1431 load(1, false, true);
1432 }
1433 fCurrentEntity.position++;
1434 if (fCurrentEntity.ch[fCurrentEntity.position] == '\n') {
1435 fCurrentEntity.position++;
1436 }
1437 fCurrentEntity.lineNumber++;
1438 fCurrentEntity.columnNumber = 1;
1439 if (DEBUG_BUFFER) {
1440 System.out.print(")skipChar, '"+(char)c+"': ");
1441 print();
1442 System.out.println(" -> true");
1443 }
1444 return true;
1445 }
1446
1447 // character was not skipped
1448 if (DEBUG_BUFFER) {
1449 System.out.print(")skipChar, '"+(char)c+"': ");
1450 print();
1451 System.out.println(" -> false");
1462 * <p>
1463 * <strong>Note:</strong> The characters are consumed only if they are
1464 * space characters.
1465 *
1466 * @return Returns true if at least one space character was skipped.
1467 *
1468 * @throws IOException Thrown if i/o error occurs.
1469 * @throws EOFException Thrown on end of file.
1470 *
1471 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
1472 */
1473 public boolean skipSpaces() throws IOException {
1474 if (DEBUG_BUFFER) {
1475 System.out.print("(skipSpaces: ");
1476 print();
1477 System.out.println();
1478 }
1479 //boolean entityChanged = false;
1480 // load more characters, if needed
1481 if (fCurrentEntity.position == fCurrentEntity.count) {
1482 load(0, true, true);
1483 }
1484
1485 //we are doing this check only in skipSpace() because it is called by
1486 //fMiscDispatcher and we want the parser to exit gracefully when document
1487 //is well-formed.
1488 //it is possible that end of document is reached and
1489 //fCurrentEntity becomes null
1490 //nothing was read so entity changed 'false' should be returned.
1491 if(fCurrentEntity == null){
1492 return false ;
1493 }
1494
1495 // skip spaces
1496 int c = fCurrentEntity.ch[fCurrentEntity.position];
1497 if (XMLChar.isSpace(c)) {
1498 do {
1499 boolean entityChanged = false;
1500 // handle newlines
1501 if (c == '\n' || (isExternal && c == '\r')) {
1502 fCurrentEntity.lineNumber++;
1503 fCurrentEntity.columnNumber = 1;
1504 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
1505 fCurrentEntity.ch[0] = (char)c;
1506 entityChanged = load(1, true, true);
1507 if (!entityChanged){
1508 // the load change the position to be 1,
1509 // need to restore it when entity not changed
1510 fCurrentEntity.position = 0;
1511 }else if(fCurrentEntity == null){
1512 return true ;
1513 }
1514 }
1515 if (c == '\r' && isExternal) {
1516 // REVISIT: Does this need to be updated to fix the
1517 // #x0D ^#x0A newline normalization problem? -Ac
1518 if (fCurrentEntity.ch[++fCurrentEntity.position] != '\n') {
1519 fCurrentEntity.position--;
1520 }
1521 }
1522 } else {
1523 fCurrentEntity.columnNumber++;
1524 }
1525 // load more characters, if needed
1526 if (!entityChanged){
1527 fCurrentEntity.position++;
1528 }
1529
1530 if (fCurrentEntity.position == fCurrentEntity.count) {
1531 load(0, true, true);
1532
1533 //we are doing this check only in skipSpace() because it is called by
1534 //fMiscDispatcher and we want the parser to exit gracefully when document
1535 //is well-formed.
1536
1537 //it is possible that end of document is reached and
1538 //fCurrentEntity becomes null
1539 //nothing was read so entity changed 'false' should be returned.
1540 if(fCurrentEntity == null){
1541 return true ;
1542 }
1543
1544 }
1545 } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
1546 if (DEBUG_BUFFER) {
1547 System.out.print(")skipSpaces: ");
1548 print();
1549 System.out.println(" -> true");
1550 }
1551 return true;
1587 return true;
1588 }
1589 if(DEBUG_SKIP_STRING){
1590 System.out.println("fCurrentEntity.count = " + fCurrentEntity.count);
1591 System.out.println("fCurrentEntity.position = " + fCurrentEntity.position);
1592 System.out.println("length = " + length);
1593 }
1594 boolean entityChanged = false;
1595 //load more characters -- this function shouldn't change the entity
1596 while((fCurrentEntity.count - fCurrentEntity.position) < length){
1597 if( (fCurrentEntity.ch.length - fCurrentEntity.position) < length){
1598 invokeListeners(0);
1599 System.arraycopy(fCurrentEntity.ch, fCurrentEntity.position, fCurrentEntity.ch,0,fCurrentEntity.count - fCurrentEntity.position);
1600 fCurrentEntity.count = fCurrentEntity.count - fCurrentEntity.position;
1601 fCurrentEntity.position = 0;
1602 }
1603
1604 if((fCurrentEntity.count - fCurrentEntity.position) < length){
1605 int pos = fCurrentEntity.position;
1606 invokeListeners(pos);
1607 entityChanged = load(fCurrentEntity.count, changeEntity, false);
1608 fCurrentEntity.position = pos;
1609 if(entityChanged)break;
1610 }
1611 if(DEBUG_SKIP_STRING){
1612 System.out.println("fCurrentEntity.count = " + fCurrentEntity.count);
1613 System.out.println("fCurrentEntity.position = " + fCurrentEntity.position);
1614 System.out.println("length = " + length);
1615 }
1616 }
1617 //load changes the position.. set it back to the point where we started.
1618
1619 //after loading check again.
1620 if((fCurrentEntity.count - fCurrentEntity.position) >= length) {
1621 return true;
1622 } else {
1623 return false;
1624 }
1625 }
1626
1627 /**
1692 return false;
1693 }
1694
1695 //
1696 // Locator methods
1697 //
1698 //
1699 // Private methods
1700 //
1701
1702 /**
1703 * Loads a chunk of text.
1704 *
1705 * @param offset The offset into the character buffer to
1706 * read the next batch of characters.
1707 * @param changeEntity True if the load should change entities
1708 * at the end of the entity, otherwise leave
1709 * the current entity in place and the entity
1710 * boundary will be signaled by the return
1711 * value.
1712 * @param notify Determine whether to notify listeners of
1713 * the event
1714 *
1715 * @returns Returns true if the entity changed as a result of this
1716 * load operation.
1717 */
1718 final boolean load(int offset, boolean changeEntity, boolean notify)
1719 throws IOException {
1720 if (DEBUG_BUFFER) {
1721 System.out.print("(load, "+offset+": ");
1722 print();
1723 System.out.println();
1724 }
1725 if (notify) {
1726 invokeListeners(offset);
1727 }
1728 //maintaing the count till last load
1729 fCurrentEntity.fTotalCountTillLastLoad = fCurrentEntity.fTotalCountTillLastLoad + fCurrentEntity.fLastCount ;
1730 // read characters
1731 int length = fCurrentEntity.ch.length - offset;
1732 if (!fCurrentEntity.mayReadChunks && length > XMLEntityManager.DEFAULT_XMLDECL_BUFFER_SIZE) {
1733 length = XMLEntityManager.DEFAULT_XMLDECL_BUFFER_SIZE;
1734 }
1735 if (DEBUG_BUFFER) System.out.println(" length to try to read: "+length);
1736 int count = fCurrentEntity.reader.read(fCurrentEntity.ch, offset, length);
1737 if (DEBUG_BUFFER) System.out.println(" length actually read: "+count);
1738
1739 // reset count and position
1740 boolean entityChanged = false;
1741 if (count != -1) {
1742 if (count != 0) {
1743 // record the last count
1744 fCurrentEntity.fLastCount = count;
1745 fCurrentEntity.count = count + offset;
1746 fCurrentEntity.position = offset;
1747 }
1748 }
1749 // end of this entity
1750 else {
1751 fCurrentEntity.count = offset;
1752 fCurrentEntity.position = offset;
1753 entityChanged = true;
1754
1755 if (changeEntity) {
1756 //notify the entity manager about the end of entity
1757 fEntityManager.endEntity();
1758 //return if the current entity becomes null
1759 if(fCurrentEntity == null){
1760 throw END_OF_DOCUMENT_ENTITY;
1761 }
1762 // handle the trailing edges
1763 if (fCurrentEntity.position == fCurrentEntity.count) {
1764 load(0, true, false);
1765 }
1766 }
1767
1768 }
1769 if (DEBUG_BUFFER) {
1770 System.out.print(")load, "+offset+": ");
1771 print();
1772 System.out.println();
1773 }
1774
1775 return entityChanged;
1776
1777 } // load(int, boolean):boolean
1778
1779 /**
1780 * Creates a reader capable of reading the given input stream in
1781 * the specified encoding.
1782 *
1783 * @param inputStream The input stream.
1784 * @param encoding The encoding name that the input stream is
2041 } else {
2042 System.out.print("*NO CURRENT ENTITY*");
2043 }
2044 }
2045 }
2046
2047 /**
2048 * Registers the listener object and provides callback.
2049 * @param listener listener to which call back should be provided when scanner buffer
2050 * is being changed.
2051 */
2052 public void registerListener(XMLBufferListener listener) {
2053 if(!listeners.contains(listener))
2054 listeners.add(listener);
2055 }
2056
2057 /**
2058 *
2059 * @param loadPos Starting position from which new data is being loaded into scanner buffer.
2060 */
2061 public void invokeListeners(int loadPos){
2062 for(int i=0;i<listeners.size();i++){
2063 XMLBufferListener listener =(XMLBufferListener) listeners.get(i);
2064 listener.refresh(loadPos);
2065 }
2066 }
2067
2068 /**
2069 * Skips space characters appearing immediately on the input that would
2070 * match non-terminal S (0x09, 0x0A, 0x0D, 0x20) before end of line
2071 * normalization is performed. This is useful when scanning structures
2072 * such as the XMLDecl and TextDecl that can only contain US-ASCII
2073 * characters.
2074 * <p>
2075 * <strong>Note:</strong> The characters are consumed only if they would
2076 * match non-terminal S before end of line normalization is performed.
2077 *
2078 * @return Returns true if at least one space character was skipped.
2079 *
2080 * @throws IOException Thrown if i/o error occurs.
2081 * @throws EOFException Thrown on end of file.
2082 *
2083 * @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
2084 */
2085 public final boolean skipDeclSpaces() throws IOException {
2086 if (DEBUG_BUFFER) {
2087 System.out.print("(skipDeclSpaces: ");
2088 //XMLEntityManager.print(fCurrentEntity);
2089 System.out.println();
2090 }
2091
2092 // load more characters, if needed
2093 if (fCurrentEntity.position == fCurrentEntity.count) {
2094 load(0, true, false);
2095 }
2096
2097 // skip spaces
2098 int c = fCurrentEntity.ch[fCurrentEntity.position];
2099 if (XMLChar.isSpace(c)) {
2100 boolean external = fCurrentEntity.isExternal();
2101 do {
2102 boolean entityChanged = false;
2103 // handle newlines
2104 if (c == '\n' || (external && c == '\r')) {
2105 fCurrentEntity.lineNumber++;
2106 fCurrentEntity.columnNumber = 1;
2107 if (fCurrentEntity.position == fCurrentEntity.count - 1) {
2108 fCurrentEntity.ch[0] = (char)c;
2109 entityChanged = load(1, true, false);
2110 if (!entityChanged)
2111 // the load change the position to be 1,
2112 // need to restore it when entity not changed
2113 fCurrentEntity.position = 0;
2114 }
2115 if (c == '\r' && external) {
2116 // REVISIT: Does this need to be updated to fix the
2117 // #x0D ^#x0A newline normalization problem? -Ac
2118 if (fCurrentEntity.ch[++fCurrentEntity.position] != '\n') {
2119 fCurrentEntity.position--;
2120 }
2121 }
2122 /*** NEWLINE NORMALIZATION ***
2123 * else {
2124 * if (fCurrentEntity.ch[fCurrentEntity.position + 1] == '\r'
2125 * && external) {
2126 * fCurrentEntity.position++;
2127 * }
2128 * }
2129 * /***/
2130 } else {
2131 fCurrentEntity.columnNumber++;
2132 }
2133 // load more characters, if needed
2134 if (!entityChanged)
2135 fCurrentEntity.position++;
2136 if (fCurrentEntity.position == fCurrentEntity.count) {
2137 load(0, true, false);
2138 }
2139 } while (XMLChar.isSpace(c = fCurrentEntity.ch[fCurrentEntity.position]));
2140 if (DEBUG_BUFFER) {
2141 System.out.print(")skipDeclSpaces: ");
2142 // XMLEntityManager.print(fCurrentEntity);
2143 System.out.println(" -> true");
2144 }
2145 return true;
2146 }
2147
2148 // no spaces were found
2149 if (DEBUG_BUFFER) {
2150 System.out.print(")skipDeclSpaces: ");
2151 //XMLEntityManager.print(fCurrentEntity);
2152 System.out.println(" -> false");
2153 }
2154 return false;
2155
2156 } // skipDeclSpaces():boolean
2157
|