001: package com.jclark.xml.tok;
002:
003: /**
004: * Represents information returned by <code>Encoding.tokenizeContent</code>.
005: * @see Encoding#tokenizeContent
006: * @version $Revision: 1.3 $ $Date: 1998/02/17 04:23:51 $
007: */
008: public class ContentToken extends Token {
009: private static final int INIT_ATT_COUNT = 8;
010: private int attCount = 0;
011: private int[] attNameStart = new int[INIT_ATT_COUNT];
012: private int[] attNameEnd = new int[INIT_ATT_COUNT];
013: private int[] attValueStart = new int[INIT_ATT_COUNT];
014: private int[] attValueEnd = new int[INIT_ATT_COUNT];
015: private boolean[] attNormalized = new boolean[INIT_ATT_COUNT];
016:
017: /**
018: * Returns the number of attributes specified in the start-tag
019: * or empty element tag.
020: */
021: public final int getAttributeSpecifiedCount() {
022: return attCount;
023: }
024:
025: /**
026: * Returns the index of the first character of the name of the
027: * attribute index <code>i</code>.
028: */
029: public final int getAttributeNameStart(int i) {
030: if (i >= attCount)
031: throw new IndexOutOfBoundsException();
032: return attNameStart[i];
033: }
034:
035: /**
036: * Returns the index following the last character of the name of the
037: * attribute index <code>i</code>.
038: */
039: public final int getAttributeNameEnd(int i) {
040: if (i >= attCount)
041: throw new IndexOutOfBoundsException();
042: return attNameEnd[i];
043: }
044:
045: /**
046: * Returns the index of the character following the opening quote of
047: * attribute index <code>i</code>.
048: */
049: public final int getAttributeValueStart(int i) {
050: if (i >= attCount)
051: throw new IndexOutOfBoundsException();
052: return attValueStart[i];
053: }
054:
055: /**
056: * Returns the index of the closing quote attribute index <code>i</code>.
057: */
058: public final int getAttributeValueEnd(int i) {
059: if (i >= attCount)
060: throw new IndexOutOfBoundsException();
061: return attValueEnd[i];
062: }
063:
064: /**
065: * Returns true if attribute index <code>i</code> does not need to
066: * be normalized. This is an optimization that allows further processing
067: * of the attribute to be avoided when it is known that normalization
068: * cannot change the value of the attribute.
069: */
070: public final boolean isAttributeNormalized(int i) {
071: if (i >= attCount)
072: throw new IndexOutOfBoundsException();
073: return attNormalized[i];
074: }
075:
076: final void clearAttributes() {
077: attCount = 0;
078: }
079:
080: final void appendAttribute(int nameStart, int nameEnd,
081: int valueStart, int valueEnd, boolean normalized) {
082: if (attCount == attNameStart.length) {
083: attNameStart = grow(attNameStart);
084: attNameEnd = grow(attNameEnd);
085: attValueStart = grow(attValueStart);
086: attValueEnd = grow(attValueEnd);
087: attNormalized = grow(attNormalized);
088: }
089: attNameStart[attCount] = nameStart;
090: attNameEnd[attCount] = nameEnd;
091: attValueStart[attCount] = valueStart;
092: attValueEnd[attCount] = valueEnd;
093: attNormalized[attCount] = normalized;
094: ++attCount;
095: }
096:
097: final void checkAttributeUniqueness(byte[] buf)
098: throws InvalidTokenException {
099: for (int i = 1; i < attCount; i++) {
100: int len = attNameEnd[i] - attNameStart[i];
101: for (int j = 0; j < i; j++) {
102: if (attNameEnd[j] - attNameStart[j] == len) {
103: int n = len;
104: int s1 = attNameStart[i];
105: int s2 = attNameStart[j];
106: do {
107: if (--n < 0)
108: throw new InvalidTokenException(
109: attNameStart[i],
110: InvalidTokenException.DUPLICATE_ATTRIBUTE);
111: } while (buf[s1++] == buf[s2++]);
112: }
113: }
114: }
115: }
116:
117: private static final int[] grow(int[] v) {
118: int[] tem = v;
119: v = new int[tem.length << 1];
120: System.arraycopy(tem, 0, v, 0, tem.length);
121: return v;
122: }
123:
124: private static final boolean[] grow(boolean[] v) {
125: boolean[] tem = v;
126: v = new boolean[tem.length << 1];
127: System.arraycopy(tem, 0, v, 0, tem.length);
128: return v;
129: }
130:
131: }
|