Source Code Cross Referenced for TreeList.java in  » Scripting » Nice » gnu » lists » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » Nice » gnu.lists 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // Copyright (c) 2001  Per M.A. Bothner and Brainfood Inc.
0002:        // This is free software;  for terms and warranty disclaimer see ./COPYING.
0003:
0004:        package gnu.lists;
0005:
0006:        /** A compact representation of a tree, that is a nested list structure.
0007:         * The data structure can store anything that can be emitted to a Consumer.
0008:         * This data structure is optimized for efficient forwards traversal
0009:         * through the data structure, not random access.
0010:         * It does have an "insertion point"; insertions and deletions are
0011:         * efficient through the use of a buffer gap.
0012:         * It is a reasonable choice for a "DOM" for XML data.
0013:         */
0014:
0015:        public class TreeList extends AbstractSequence implements  Consumer,
0016:                PositionConsumer, Consumable {
0017:            // Some public fields and methods are public which probably shouldn't be,
0018:            // for the sake of NamespaceResolver.  FIXME.  Perhaps an abstract class
0019:            // in gnu.lists that NamespaceResolver could extend?
0020:
0021:            public Object[] objects;
0022:            static final Object availObject = new String("(AVAIL");
0023:            public char[] data;
0024:            public int gapStart;
0025:            public int gapEnd;
0026:
0027:            /** If non-zero, gap is in an attribute starting (1 less than) here. */
0028:            public int attrStart;
0029:
0030:            public TreeList() {
0031:                resizeObjects();
0032:                gapEnd = 200;
0033:                data = new char[gapEnd];
0034:            }
0035:
0036:            /**
0037:             * Make a copy of a sub-range of a TreeList.
0038:             * @param list the TreeList to copy
0039:             * @param startPosition start of range, as a raw index in data
0040:             * @param endPosition end of range, as a raw index in data
0041:             */
0042:            public TreeList(TreeList list, int startPosition, int endPosition) {
0043:                this ();
0044:                list.consumeRange(startPosition, endPosition, this );
0045:            }
0046:
0047:            public TreeList(TreeList list) {
0048:                this (list, 0, list.data.length);
0049:            }
0050:
0051:            public void clear() {
0052:                gapStart = 0;
0053:                gapEnd = data.length;
0054:                attrStart = 0;
0055:                if (gapEnd > 1500) {
0056:                    gapEnd = 200;
0057:                    data = new char[gapEnd];
0058:                }
0059:                objects = null;
0060:                resizeObjects();
0061:            }
0062:
0063:            // The data array contains an encoding of values, as follows:
0064:            // 0x0000 ... 0x9FFF:  A single Unicode character.
0065:            // 0xAXXX: BEGIN_GROUP_SHORT
0066:            // 0xBXXX:  negative integer ((short)0x0XXX<<4)>>4, range -4096 to -1
0067:            // 0xCXXX:  positive integer 0x0XXX, in the range 0 to 4095
0068:            // 0xDXXX:  positive integer 0x1XXX, in the range 4096 to 8191
0069:            // 0xEXXX:: OBJECT_REF_SHORT.  The object in objects[0xXXX].
0070:            // 0xF0XX:  A byte (encoded character or char fragment) ((byte) 0xXX).
0071:            // 0xF100 ... 0xF101:  A Boolean (BOOL_FALSE, BOOL_TRUE)
0072:            // 0xF102 A B:      INT_FOLLOWS - 32-bit int (big-endian)
0073:            // 0xF103 A B C D:  LONG_FOLLOWS 64-bit long int (big-endian)
0074:            // 0xF104 A B:      FLOAT_FOLLOWS 32-bit float (big-endian)
0075:            // 0xF105 A B C D:  DOUBLE_FOLLOWS 64-bit double (big-endian)
0076:            // 0xF106: CHAR_FOLLOWS
0077:            // 0xF107: CHAR_PAIR_FOLLOWS
0078:            // 0xF108: BEGIN_GROUP_LONG
0079:            // 0xF109: BEGIN_ATTRIBUTE_LONG
0080:            // 0xF10A: END_ATTRIBUTE
0081:            // 0xF10B: END_GROUP_SHORT
0082:            // 0xF10C: END_GROUP_LONG
0083:            // 0xF10D A B: OBJECT_REF_FOLLOWS:  The object in objects[(A,B)].
0084:            // 0xF10E A B: POSITION_REF_FOLLOWS:  The TreePosition in objects[(A,B)].
0085:            // 0xF10F A B C D E F: POSITION_TRIPLE_FOLLOWS
0086:            // 0xF110 BEGIN_DOCUMENT
0087:
0088:            /** The largest Unicode character that can be encoded in one char. */
0089:            static final int MAX_CHAR_SHORT = 0x9FFF;
0090:
0091:            /** The smallest integer that can use the short int encoding. */
0092:            static final int MIN_INT_SHORT = -0x1000; // -4096
0093:
0094:            /** The largest integer that can use the short int encoding. */
0095:            static final int MAX_INT_SHORT = 0x1FFF; // 8191
0096:
0097:            /** The value used to encode the integer zero. */
0098:            static final int INT_SHORT_ZERO = 0xC000;
0099:
0100:            /** The value used to encode the object in objects[0]. */
0101:            static final int OBJECT_REF_SHORT = 0xE000;
0102:
0103:            /** The maximum offset in the objects array for a short object-ref. */
0104:            static final int OBJECT_REF_SHORT_INDEX_MAX = 0xFFF;
0105:
0106:            /** Followed by 2 chars that provide an index into objects. */
0107:            static final char OBJECT_REF_FOLLOWS = 0xF10D;
0108:
0109:            /** Followed by 2 chars that provide an index into objects. */
0110:            static final char POSITION_REF_FOLLOWS = 0xF10E;
0111:
0112:            /** A position triple referenceing some other "nodes".
0113:             * Followed by index of squence (2 chars), ipos (2 chars), and
0114:             * index of xpos or -1 if xpos==null (2 chars). */
0115:            static final char POSITION_TRIPLE_FOLLOWS = 0xF10F;
0116:
0117:            /** Encoding prefix that indicates a byte value. */
0118:            static final int BYTE_PREFIX = 0xF000;
0119:
0120:            /** The value used to encode false. */
0121:            static final char BOOL_FALSE = 0xF100;
0122:
0123:            /** The value used to encode true. */
0124:            static final char BOOL_TRUE = 0xF101;
0125:
0126:            /** A 32-bit integer, non-compact form.
0127:             *
0128:             * [INT_FOLLOWS]
0129:             * [word1], [word2]:  The big-endian bits of the integer.
0130:             */
0131:            static final int INT_FOLLOWS = 0xF102;
0132:
0133:            /** A 64-bit long integer.
0134:             *
0135:             * [LONG_FOLLOWS]
0136:             * [word1], [word2], [word3], [word4]:  The big-endian bits of the long.
0137:             */
0138:            static final int LONG_FOLLOWS = 0xF103;
0139:
0140:            /** A 64-bit float floating-pointer number.
0141:             *
0142:             * [FLOAT_FOLLOWS]
0143:             * [word1], [word2]:  The big-endian bits of the float.
0144:             */
0145:            static final int FLOAT_FOLLOWS = 0xF104;
0146:
0147:            /** A 64-bit double floating-pointer number.
0148:             *
0149:             * [DOUBLE_FOLLOWS]
0150:             * [word1], [word2], [word3], [word4]:  The big-endian bits of the double.
0151:             */
0152:            static final int DOUBLE_FOLLOWS = 0xF105;
0153:
0154:            /** A 16-bit (non-compact) Unicode char follows. */
0155:            static final int CHAR_FOLLOWS = 0xF106;
0156:
0157:            /** A surrogate pair follows.  (not implemented). */
0158:            static final int CHAR_PAIR_FOLLOWS = CHAR_FOLLOWS + 1;
0159:
0160:            /** The beginning of an attribute.
0161:             * [BEGIN_ATTRIBUTE_LONG]
0162:             * [index], 2 shorts, where objects[index] is the attribute type name
0163:             *   and objects[index+1] is the attribute type object.
0164:             * [end_offset], 2 shorts, giving the location of the following
0165:             *   END_ATTRIBUTE.  If the attribute straddles the gap, then
0166:             *   end_offset is a negative offset relative to data.length.
0167:             *   (Therefore allocating more space for the gap does not require
0168:             *   adjusting end_offset.)  Otherwise, the end_offset is relative
0169:             *   to the BEGIN_ATTRIBUTE_LONG word.
0170:             */
0171:            static final int BEGIN_ATTRIBUTE_LONG = 0xF109;
0172:
0173:            /** The end of an attribute of a node. */
0174:            static final int END_ATTRIBUTE = 0xF10A;
0175:
0176:            /** Beginning of a document.
0177:             * No parameters.  Used to distinguish a document from its element node.
0178:             */
0179:            static final int BEGIN_DOCUMENT = 0xF110;
0180:
0181:            /** Beginning of a group, compact form.
0182:             *
0183:             * [BEGIN_GROUP_SHORT + index], where objects[index] is the group's
0184:             *   type name and objects[index+1] is the type object.
0185:             * [end_offset], the unsigned offset (from the initial word)
0186:             *   to the corresponding END_GROUP_SHORT.
0187:             * [parent_offset], the (unsigned absolute value of the) offset
0188:             *   to the outer BEGIN_GROUP_SHORT/BEGIN_GROUP_LONG.  (If this is the
0189:             *   outermost group, then parent_offset==0.)
0190:             *
0191:             * This should is used when index < BEGIN_GROUP_SHORT_INDEX_MAX,
0192:             * both end_offset and parent_offset fit in 16 bits,
0193:             * and the group does not straddle the gap.
0194:             */
0195:            static final int BEGIN_GROUP_SHORT = 0xA000;
0196:            static final int BEGIN_GROUP_SHORT_INDEX_MAX = 0xFFF;
0197:
0198:            /** End of a group, compact form.
0199:             *
0200:             * [END_GROUP_SHORT]
0201:             * [begin_offset], the unsigned absolute value of the offset to the
0202:             *   matching BEGIN.  (This is the same as the matching end_offset.)
0203:             *
0204:             */
0205:            static final int END_GROUP_SHORT = 0xF10B;
0206:
0207:            /** Begin of a group, non-compact form.
0208:             *
0209:             * [BEGIN_GROUP_LONG]
0210:             * [end_offset], in 2 shorts.  The position of the matching END_GROUP_LONG.
0211:             *   If the group straddles the gap, then end_offset is a negative offset
0212:             *   relative to data.length.  (Therefore allocating more space for the
0213:             *   gap does not require adjusting any end_offset.)   If the group and
0214:             *   and its children are all on the same side of the gap, then end_offset
0215:             *   is a positive offset relative to the BEGIN_GROUP_LONG word.  (Hence
0216:             *   shifting an entire group when the gap is moved does not require
0217:             *   changing its end_offset.)
0218:             *
0219:             * Note that the space taken by a BEGIN_GROUP_LONG is the same that
0220:             * needed for a BEGIN_GROUP_SHORT (but a END_GROUP_LONG takes much
0221:             * more space than a END_GROUP_SHORT).  This is to make it easier
0222:             * to convert a BEGIN_GROUP_LONG to a BEGIN_GROUP_SHORT or vice
0223:             * versa, as needed.
0224:             */
0225:            static final int BEGIN_GROUP_LONG = 0xF108;
0226:
0227:            /** End of a group, non-compact form.
0228:             *
0229:             * [END_GROUP_LONG]
0230:             * [index], 2 shorts where objects[index] is the group's type name and
0231:             *   objects[index+1] is the type object.
0232:             * [begin_offset], in 2 shorts.  The position of the matching
0233:             *   BEGIN_GROUP_LONG.  If the group straddles the gap, then begin_offset
0234:             *   is the actual index (i.e. relative to the start of data) of the
0235:             *   matching BEGIN_GROUP_LONG.  (Therefore allocating more space for the
0236:             *   gap does not require adjusting begin_offset.)  If the group does not
0237:             *   straddle the gap, then begin_offset is a negative offset relative
0238:             *   to the END_GROUP_LONG word.  (Hence shifting an entire group when
0239:             *   the gap is moved does not require changing its begin_offset.)
0240:             *   relative to data.length.
0241:             * [parent_offset], in 2 shorts.  The position of the outer BEGIN_GROUP_LONG
0242:             *   or BEGIN_GROUP_SHORT.  If the difference straddles the gap (i.e.
0243:             *   either this group straddles the gap or the parent group does and the
0244:             *   gap precedes this group), then parent_offset is the actual index
0245:             *   of the parent group.  Otherwise, then parent_offset is a negative
0246:             *   offset relative to the END_GROUP_LONG word.
0247:             */
0248:            static final int END_GROUP_LONG = 0xF10C;
0249:
0250:            int currentBeginGroup = 0;
0251:
0252:            public void ensureSpace(int needed) {
0253:                int avail = gapEnd - gapStart;
0254:                if (needed > avail) {
0255:                    int oldSize = data.length;
0256:                    int neededSize = oldSize - avail + needed;
0257:                    int newSize = 2 * oldSize;
0258:                    if (newSize < neededSize)
0259:                        newSize = neededSize;
0260:                    char[] tmp = new char[newSize];
0261:                    if (gapStart > 0)
0262:                        System.arraycopy(data, 0, tmp, 0, gapStart);
0263:                    int afterGap = oldSize - gapEnd;
0264:                    if (afterGap > 0)
0265:                        System.arraycopy(data, gapEnd, tmp, newSize - afterGap,
0266:                                afterGap);
0267:                    gapEnd = newSize - afterGap;
0268:                    data = tmp;
0269:                }
0270:            }
0271:
0272:            public final void resizeObjects() {
0273:                int oldLength;
0274:                int newLength;
0275:                Object[] tmp;
0276:                if (objects == null) {
0277:                    oldLength = 0;
0278:                    newLength = 100;
0279:                    tmp = new Object[newLength];
0280:                } else {
0281:                    oldLength = objects.length;
0282:                    newLength = 2 * oldLength;
0283:                    tmp = new Object[newLength];
0284:                    System.arraycopy(objects, 0, tmp, 0, oldLength);
0285:                }
0286:                Object availObject = this .availObject;
0287:                for (int i = oldLength; i < newLength; i++)
0288:                    tmp[i] = availObject;
0289:                objects = tmp;
0290:            }
0291:
0292:            protected int find(Object arg1) {
0293:                // FIXME - linear search!
0294:                int i = 0;
0295:                int len = objects.length;
0296:                Object availObject = this .availObject;
0297:                int avail = -1;
0298:                for (; i < len; i++) {
0299:                    Object obj = objects[i];
0300:                    if (obj == arg1)
0301:                        return i;
0302:                    if (obj == availObject && avail < 0)
0303:                        avail = i;
0304:                }
0305:                if (avail >= 0) {
0306:                    objects[avail] = arg1;
0307:                    return avail;
0308:                }
0309:                resizeObjects();
0310:                objects[len] = arg1;
0311:                return len;
0312:            }
0313:
0314:            protected int find(Object arg1, Object arg2) {
0315:                // FIXME - linear search!
0316:                int i = 0;
0317:                int len = objects.length;
0318:                Object availObject = this .availObject; // Optimization.
0319:                int avail = -1;
0320:                Object[] objects = this .objects; // Optimization.
0321:                for (; i + 1 < len; i++) {
0322:                    Object obj1 = objects[i];
0323:                    if (obj1 == arg1 && objects[i + 1] == arg2)
0324:                        return i;
0325:                    if (avail < 0 && obj1 == availObject
0326:                            && objects[i + 1] == availObject)
0327:                        avail = i;
0328:                }
0329:                if (avail >= 0) {
0330:                    objects[avail] = arg1;
0331:                    objects[avail + 1] = arg2;
0332:                    return avail;
0333:                }
0334:                resizeObjects();
0335:                objects = this .objects;
0336:                objects[len] = arg1;
0337:                objects[len + 1] = arg2;
0338:                return len;
0339:            }
0340:
0341:            /** Get a 32-bit int from the data array. */
0342:            final protected int getIntN(int index) {
0343:                return (data[index] << 16) | (data[index + 1]);
0344:            }
0345:
0346:            /** Get a 64-bit long from the data array. */
0347:            final protected long getLongN(int index) {
0348:                char[] data = this .data; // Optimization.
0349:                return ((data[index] << 48) | (data[index + 1] << 32)
0350:                        | (data[index + 2] << 16) | data[index + 3]);
0351:            }
0352:
0353:            final public void setIntN(int index, int i) {
0354:                data[index] = (char) (i >> 16);
0355:                data[index + 1] = (char) i;
0356:            }
0357:
0358:            public boolean consume(TreePosition position) {
0359:                ensureSpace(3);
0360:                // FIXME - no need for find to search in this case!
0361:                int index = find(new TreePosition(position));
0362:                data[gapStart++] = POSITION_REF_FOLLOWS;
0363:                setIntN(gapStart, index);
0364:                gapStart += 2;
0365:                return true;
0366:            }
0367:
0368:            public boolean writePosition(AbstractSequence seq, int ipos,
0369:                    Object xpos) {
0370:                ensureSpace(7);
0371:                data[gapStart] = POSITION_TRIPLE_FOLLOWS;
0372:                int seq_index = find(seq);
0373:                int xpos_index = xpos == null ? -1 : find(xpos);
0374:                setIntN(gapStart + 1, seq_index);
0375:                setIntN(gapStart + 3, ipos);
0376:                setIntN(gapStart + 5, xpos_index);
0377:                gapStart += 7;
0378:                return true;
0379:            }
0380:
0381:            public void writeObject(Object v) {
0382:                if (v instanceof  SeqPosition) {
0383:                    // A SeqPosition is used as a temporary cursor (see NodeType),
0384:                    // so we need to save the current position.
0385:                    SeqPosition pos = (SeqPosition) v;
0386:                    writePosition(pos.sequence, pos.ipos, pos.xpos);
0387:                    return;
0388:                }
0389:                ensureSpace(3);
0390:                int index = find(v);
0391:                if (index < 0x1000)
0392:                    data[gapStart++] = (char) (OBJECT_REF_SHORT | index);
0393:                else {
0394:                    data[gapStart++] = OBJECT_REF_FOLLOWS;
0395:                    setIntN(gapStart, index);
0396:                    gapStart += 2;
0397:                }
0398:            }
0399:
0400:            public void beginGroup(String typeName, Object type) {
0401:                beginGroup(find(typeName, type));
0402:            }
0403:
0404:            public void beginDocument() {
0405:                ensureSpace(1);
0406:                data[gapStart++] = BEGIN_DOCUMENT;
0407:            }
0408:
0409:            public void endDocument() {
0410:            }
0411:
0412:            public void beginGroup(int index) {
0413:                ensureSpace(3 + 7);
0414:                gapEnd -= 7;
0415:                data[gapStart++] = BEGIN_GROUP_LONG;
0416:                setIntN(gapStart, gapEnd - data.length); // end_offset
0417:                gapStart += 2;
0418:                data[gapEnd] = END_GROUP_LONG;
0419:                setIntN(gapEnd + 1, index); // begin_offset
0420:                setIntN(gapEnd + 3, gapStart - 3); // begin_offset
0421:                setIntN(gapEnd + 5, currentBeginGroup); // parent_offset
0422:                currentBeginGroup = gapStart - 3;
0423:            }
0424:
0425:            public void endGroup(String typeName) {
0426:                if (data[gapEnd] != END_GROUP_LONG)
0427:                    throw new Error("unexpected endGroup " + typeName);
0428:                int index = getIntN(gapEnd + 1);
0429:                int begin = getIntN(gapEnd + 3);
0430:                int parent = getIntN(gapEnd + 5);
0431:                gapEnd += 7;
0432:                int offset = gapStart - begin;
0433:                int parentOffset = begin - parent;
0434:                if (index < BEGIN_GROUP_SHORT_INDEX_MAX && offset < 0x10000
0435:                        && parentOffset < 0x10000) {
0436:                    data[begin] = (char) (BEGIN_GROUP_SHORT | index);
0437:                    data[begin + 1] = (char) offset; // end_offset
0438:                    data[begin + 2] = (char) parentOffset;
0439:                    data[gapStart] = END_GROUP_SHORT;
0440:                    data[gapStart + 1] = (char) offset; // begin_offset
0441:                    gapStart += 2;
0442:                } else {
0443:                    data[begin] = BEGIN_GROUP_LONG;
0444:                    setIntN(begin + 1, offset);
0445:                    data[gapStart] = END_GROUP_LONG;
0446:                    setIntN(gapStart + 1, index);
0447:                    setIntN(gapStart + 3, -offset);
0448:                    if (parent >= gapStart || begin <= gapStart)
0449:                        parent -= gapStart;
0450:                    setIntN(gapStart + 5, parent);
0451:                    gapStart += 7;
0452:                }
0453:                currentBeginGroup = parent;
0454:            }
0455:
0456:            public void beginAttribute(String attrName, Object attrType) {
0457:                beginAttribute(find(attrName, attrType));
0458:            }
0459:
0460:            public void beginAttribute(int index) {
0461:                ensureSpace(5 + 1);
0462:                gapEnd--;
0463:                data[gapStart++] = BEGIN_ATTRIBUTE_LONG;
0464:                if (attrStart != 0)
0465:                    throw new Error("nested attribute");
0466:                attrStart = gapStart;
0467:                setIntN(gapStart, index);
0468:                setIntN(gapStart + 2, gapEnd - data.length);
0469:                gapStart += 4;
0470:                data[gapEnd] = END_ATTRIBUTE;
0471:            }
0472:
0473:            public void endAttribute() {
0474:                if (data[gapEnd] != END_ATTRIBUTE || attrStart <= 0)
0475:                    throw new Error("unexpected endAttribute");
0476:                // Move the END_ATTRIBUTES to before the gap.
0477:                gapEnd++;
0478:                setIntN(attrStart + 2, gapStart - attrStart + 1);
0479:                attrStart = 0;
0480:                data[gapStart++] = END_ATTRIBUTE;
0481:            }
0482:
0483:            public void writeChar(int i) {
0484:                ensureSpace(3);
0485:                if (i <= MAX_CHAR_SHORT)
0486:                    data[gapStart++] = (char) i;
0487:                else if (i < 0x10000) {
0488:                    data[gapStart++] = CHAR_FOLLOWS;
0489:                    data[gapStart++] = (char) i;
0490:                } else {
0491:                    data[gapStart++] = CHAR_PAIR_FOLLOWS;
0492:                    // write surrogates FIXME.
0493:                }
0494:            }
0495:
0496:            public void writeBoolean(boolean v) {
0497:                ensureSpace(1);
0498:                data[gapStart++] = v ? BOOL_TRUE : BOOL_FALSE;
0499:            }
0500:
0501:            public void writeByte(int v) {
0502:                ensureSpace(1);
0503:                data[gapStart++] = (char) (BYTE_PREFIX + (v & 0xFF));
0504:            }
0505:
0506:            public void writeInt(int v) {
0507:                ensureSpace(3);
0508:                if (v >= MIN_INT_SHORT && v <= MAX_INT_SHORT)
0509:                    data[gapStart++] = (char) (INT_SHORT_ZERO + v);
0510:                else {
0511:                    data[gapStart++] = INT_FOLLOWS;
0512:                    setIntN(gapStart, v);
0513:                    gapStart += 2;
0514:                }
0515:            }
0516:
0517:            public void writeLong(long v) {
0518:                ensureSpace(5);
0519:                data[gapStart++] = LONG_FOLLOWS;
0520:                data[gapStart++] = (char) (v >>> 48);
0521:                data[gapStart++] = (char) (v >>> 32);
0522:                data[gapStart++] = (char) (v >>> 16);
0523:                data[gapStart++] = (char) v;
0524:            }
0525:
0526:            public void writeFloat(float v) {
0527:                ensureSpace(3);
0528:                int i = Float.floatToIntBits(v);
0529:                data[gapStart++] = FLOAT_FOLLOWS;
0530:                data[gapStart++] = (char) (i >>> 16);
0531:                data[gapStart++] = (char) i;
0532:            }
0533:
0534:            public void writeDouble(double v) {
0535:                ensureSpace(5);
0536:                long l = Double.doubleToLongBits(v);
0537:                data[gapStart++] = DOUBLE_FOLLOWS;
0538:                data[gapStart++] = (char) (l >>> 48);
0539:                data[gapStart++] = (char) (l >>> 32);
0540:                data[gapStart++] = (char) (l >>> 16);
0541:                data[gapStart++] = (char) l;
0542:            }
0543:
0544:            public boolean ignoring() {
0545:                return false;
0546:            }
0547:
0548:            public void writeChars(String str) {
0549:                int len = str.length();
0550:                for (int i = 0; i < len; i++)
0551:                    writeChar(str.charAt(i));
0552:            }
0553:
0554:            public void write(char[] buf, int off, int len) {
0555:                ensureSpace(len);
0556:                while (len > 0) {
0557:                    char ch = buf[off++];
0558:                    len--;
0559:                    if (ch <= MAX_CHAR_SHORT)
0560:                        data[gapStart++] = ch;
0561:                    else {
0562:                        writeChar(ch);
0563:                        ensureSpace(len);
0564:                    }
0565:                }
0566:            }
0567:
0568:            public boolean isEmpty() {
0569:                // FIXME does not work if we allow comment() entries!
0570:                int pos = gapStart == 0 ? gapEnd : 0;
0571:                return pos == data.length;
0572:            }
0573:
0574:            public int size() {
0575:                int size = 0;
0576:                int i = 0;
0577:                for (;;) {
0578:                    i = nextDataIndex(i);
0579:                    if (i < 0)
0580:                        return size;
0581:                    size++;
0582:                }
0583:            }
0584:
0585:            protected void makePosition(int index, boolean isAfter,
0586:                    PositionContainer posSet, int posNumber) {
0587:                int i = 0;
0588:                while (--index >= 0) {
0589:                    i = nextDataIndex(i);
0590:                    if (i < 0)
0591:                        throw new IndexOutOfBoundsException();
0592:                }
0593:                posSet.setPosition(posNumber, (i << 1) | (isAfter ? 1 : 0),
0594:                        null);
0595:                posSet.setSequence(posNumber, this );
0596:            }
0597:
0598:            public boolean gotoChildrenStart(TreePosition pos) {
0599:                int index = gotoChildrenStart(pos.ipos >> 1);
0600:                if (index < 0)
0601:                    return false;
0602:                pos.push(this , index << 1, null);
0603:                return true;
0604:            }
0605:
0606:            public int gotoChildrenStart(int index) {
0607:                if (index >= gapStart)
0608:                    index += gapEnd - gapStart;
0609:                if (index == data.length)
0610:                    return -1;
0611:                char datum = data[index];
0612:                if ((datum >= BEGIN_GROUP_SHORT && datum <= BEGIN_GROUP_SHORT
0613:                        + BEGIN_GROUP_SHORT_INDEX_MAX)
0614:                        || datum == BEGIN_GROUP_LONG)
0615:                    index += 3;
0616:                else if (datum == BEGIN_DOCUMENT)
0617:                    return index + 1;
0618:                else
0619:                    return -1;
0620:                for (;;) {
0621:                    if (index >= gapStart)
0622:                        index += gapEnd - gapStart;
0623:                    datum = data[index];
0624:                    if (datum == BEGIN_ATTRIBUTE_LONG) {
0625:                        int end = getIntN(index + 3);
0626:                        index = end + (end < 0 ? data.length : index);
0627:                    } else if (datum == END_ATTRIBUTE)
0628:                        index++;
0629:                    else
0630:                        break;
0631:                }
0632:                return index;
0633:            }
0634:
0635:            public boolean gotoAttributesStart(TreePosition pos) {
0636:                int index = gotoAttributesStart(pos.ipos >> 1);
0637:                if (index < 0)
0638:                    return false;
0639:                pos.push(this , index << 1, null);
0640:                return true;
0641:            }
0642:
0643:            public int gotoAttributesStart(int index) {
0644:                if (index >= gapStart)
0645:                    index += gapEnd - gapStart;
0646:                if (index == data.length)
0647:                    return -1;
0648:                char datum = data[index];
0649:                if ((datum >= BEGIN_GROUP_SHORT && datum <= BEGIN_GROUP_SHORT
0650:                        + BEGIN_GROUP_SHORT_INDEX_MAX)
0651:                        || datum == BEGIN_GROUP_LONG)
0652:                    return index + 3;
0653:                else
0654:                    return -1;
0655:            }
0656:
0657:            public Object get(int index) {
0658:                throw unsupported("get");
0659:            }
0660:
0661:            public boolean consumeNext(int ipos, Object xpos, Consumer out) {
0662:                if (!hasNext(ipos, xpos))
0663:                    return false;
0664:                int start = ipos >> 1;
0665:                int end = nextDataIndex(start);
0666:                if (end >= 0)
0667:                    consumeRange(start, end, out);
0668:                return true;
0669:            }
0670:
0671:            public int consumeRange(int startPosition, int endPosition,
0672:                    Consumer out) {
0673:                int pos = startPosition;
0674:                int limit = startPosition <= gapStart && endPosition > gapStart ? gapStart
0675:                        : endPosition;
0676:                int index;
0677:                for (;;) {
0678:                    if (pos >= limit) {
0679:                        if (pos == gapStart && endPosition > gapEnd) {
0680:
0681:                            pos = gapEnd;
0682:                            limit = endPosition;
0683:                        } else
0684:                            break;
0685:                    }
0686:
0687:                    char datum = data[pos++];
0688:
0689:                    if (datum <= MAX_CHAR_SHORT) {
0690:                        int start = pos - 1;
0691:                        int lim = limit;
0692:                        for (;;) {
0693:                            if (pos >= lim)
0694:                                break;
0695:                            datum = data[pos++];
0696:                            if (datum > MAX_CHAR_SHORT) {
0697:                                pos--;
0698:                                break;
0699:                            }
0700:                        }
0701:                        out.write(data, start, pos - start);
0702:                        continue;
0703:                    }
0704:                    if (datum >= OBJECT_REF_SHORT
0705:                            && datum <= OBJECT_REF_SHORT
0706:                                    + OBJECT_REF_SHORT_INDEX_MAX) {
0707:                        out.writeObject(objects[datum - OBJECT_REF_SHORT]);
0708:                        continue;
0709:                    }
0710:                    if (datum >= BEGIN_GROUP_SHORT
0711:                            && datum <= BEGIN_GROUP_SHORT
0712:                                    + BEGIN_GROUP_SHORT_INDEX_MAX) {
0713:                        index = datum - BEGIN_GROUP_SHORT;
0714:                        out.beginGroup(objects[index].toString(),
0715:                                objects[index + 1]);
0716:                        pos += 2;
0717:                        continue;
0718:                    }
0719:                    /*
0720:                    if ((datum & 0xFF00) == BYTE_PREFIX)
0721:                      {
0722:                        out.writeByte((byte) datum);
0723:                        continue;
0724:                      }
0725:                     */
0726:                    if (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
0727:                            && datum <= INT_SHORT_ZERO + MAX_INT_SHORT) {
0728:                        out.writeInt(datum - INT_SHORT_ZERO);
0729:                        continue;
0730:                    }
0731:                    switch (datum) {
0732:                    case BEGIN_DOCUMENT:
0733:                        continue;
0734:                    case BOOL_FALSE:
0735:                    case BOOL_TRUE:
0736:                        out.writeBoolean(datum != BOOL_FALSE);
0737:                        continue;
0738:                    case CHAR_FOLLOWS:
0739:                        out.write(data, pos, 1 + datum - CHAR_FOLLOWS);
0740:                        pos++;
0741:                        continue;
0742:                    case CHAR_PAIR_FOLLOWS:
0743:                        out.write(data, pos, 1 + datum - CHAR_FOLLOWS);
0744:                        pos += 2;
0745:                        continue;
0746:                    case POSITION_TRIPLE_FOLLOWS: {
0747:                        AbstractSequence seq = (AbstractSequence) objects[getIntN(pos)];
0748:                        int ipos = getIntN(pos + 2);
0749:                        int xpos_index = getIntN(pos + 4);
0750:                        Object xpos = xpos_index < 0 ? null
0751:                                : objects[xpos_index];
0752:                        if (out instanceof  PositionConsumer)
0753:                            ((PositionConsumer) out).writePosition(seq, ipos,
0754:                                    xpos);
0755:                        else
0756:                            out.writeObject(SeqPosition.make(seq, ipos, xpos));
0757:                        pos += 6;
0758:                    }
0759:                        continue;
0760:                    case POSITION_REF_FOLLOWS:
0761:                        if (out instanceof  PositionConsumer) {
0762:                            ((PositionConsumer) out)
0763:                                    .consume((TreePosition) objects[getIntN(pos)]);
0764:                            pos += 2;
0765:                            continue;
0766:                        }
0767:                        // ... else fall through ...
0768:                    case OBJECT_REF_FOLLOWS:
0769:                        out.writeObject(objects[getIntN(pos)]);
0770:                        pos += 2;
0771:                        continue;
0772:                    case END_GROUP_SHORT:
0773:                        index = data[pos++];
0774:                        index = data[pos - 2 - index] - BEGIN_GROUP_SHORT;
0775:                        out.endGroup(objects[index].toString());
0776:                        continue;
0777:                    case BEGIN_GROUP_LONG:
0778:                        index = getIntN(pos);
0779:                        pos += 2;
0780:                        index += index >= 0 ? pos - 1 : data.length;
0781:                        index = getIntN(index + 1);
0782:                        out.beginGroup(objects[index].toString(),
0783:                                objects[index + 1]);
0784:                        continue;
0785:                    case END_GROUP_LONG:
0786:                        index = getIntN(pos);
0787:                        out.endGroup(objects[index].toString());
0788:                        pos += 6;
0789:                        continue;
0790:                    case BEGIN_ATTRIBUTE_LONG:
0791:                        index = getIntN(pos);
0792:                        out.beginAttribute(objects[index].toString(),
0793:                                objects[index + 1]);
0794:                        pos += 4;
0795:                        continue;
0796:                    case END_ATTRIBUTE:
0797:                        out.endAttribute();
0798:                        continue;
0799:                    case INT_FOLLOWS:
0800:                        writeInt(getIntN(pos));
0801:                        pos += 2;
0802:                        continue;
0803:                    case FLOAT_FOLLOWS:
0804:                        writeFloat(Float.intBitsToFloat(getIntN(pos)));
0805:                        pos += 2;
0806:                        continue;
0807:                    case LONG_FOLLOWS:
0808:                        writeLong(getLongN(pos));
0809:                        pos += 4;
0810:                        continue;
0811:                    case DOUBLE_FOLLOWS:
0812:                        writeDouble(Double.longBitsToDouble(getLongN(pos)));
0813:                        pos += 4;
0814:                        continue;
0815:                    default:
0816:                        dump();
0817:                        throw new Error("unknown code:" + (int) datum);
0818:                    }
0819:                }
0820:                return pos;
0821:            }
0822:
0823:            public boolean hasNext(int ipos, Object xpos) {
0824:                int index = ipos >>> 1;
0825:                if (index >= gapStart)
0826:                    index += gapEnd - gapStart;
0827:                if (index == data.length)
0828:                    return false;
0829:                char ch = data[index];
0830:                return ch != END_ATTRIBUTE && ch != END_GROUP_SHORT
0831:                        && ch != END_GROUP_LONG;
0832:            }
0833:
0834:            public int getNextKind(int ipos, Object xpos) {
0835:                int index = ipos >>> 1;
0836:                if (index >= gapStart)
0837:                    index += gapEnd - gapStart;
0838:                if (index == data.length)
0839:                    return Sequence.EOF_VALUE;
0840:                char datum = data[index];
0841:                if (datum <= MAX_CHAR_SHORT)
0842:                    return Sequence.CHAR_VALUE;
0843:                if (datum >= OBJECT_REF_SHORT
0844:                        && datum <= OBJECT_REF_SHORT
0845:                                + OBJECT_REF_SHORT_INDEX_MAX)
0846:                    return Sequence.OBJECT_VALUE;
0847:                if (datum >= BEGIN_GROUP_SHORT
0848:                        && datum <= BEGIN_GROUP_SHORT
0849:                                + BEGIN_GROUP_SHORT_INDEX_MAX)
0850:                    return Sequence.GROUP_VALUE;
0851:                if ((datum & 0xFF00) == BYTE_PREFIX)
0852:                    return Sequence.TEXT_BYTE_VALUE;
0853:                if (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
0854:                        && datum <= INT_SHORT_ZERO + MAX_INT_SHORT)
0855:                    return Sequence.INT_S32_VALUE;
0856:                switch (datum) {
0857:                case BOOL_FALSE:
0858:                case BOOL_TRUE:
0859:                    return Sequence.BOOLEAN_VALUE;
0860:                case INT_FOLLOWS:
0861:                    return Sequence.INT_S32_VALUE;
0862:                case LONG_FOLLOWS:
0863:                    return Sequence.INT_S64_VALUE;
0864:                case FLOAT_FOLLOWS:
0865:                    return Sequence.FLOAT_VALUE;
0866:                case DOUBLE_FOLLOWS:
0867:                    return Sequence.DOUBLE_VALUE;
0868:                case CHAR_FOLLOWS:
0869:                case CHAR_PAIR_FOLLOWS:
0870:                    return Sequence.CHAR_VALUE;
0871:                case BEGIN_DOCUMENT:
0872:                    return Sequence.DOCUMENT_VALUE;
0873:                case BEGIN_GROUP_LONG:
0874:                    return Sequence.GROUP_VALUE;
0875:                case END_GROUP_SHORT:
0876:                case END_GROUP_LONG:
0877:                case END_ATTRIBUTE:
0878:                    return Sequence.EOF_VALUE;
0879:                case BEGIN_ATTRIBUTE_LONG:
0880:                    return Sequence.ATTRIBUTE_VALUE;
0881:                case POSITION_REF_FOLLOWS: // FIXME	
0882:                case POSITION_TRIPLE_FOLLOWS:
0883:                case OBJECT_REF_FOLLOWS:
0884:                default:
0885:                    return Sequence.OBJECT_VALUE;
0886:                }
0887:
0888:            }
0889:
0890:            protected int getNextTypeIndex(int ipos, Object xpos) {
0891:                int index = ipos >>> 1;
0892:                if (index >= gapStart)
0893:                    index += gapEnd - gapStart;
0894:                if (index == data.length)
0895:                    return Sequence.EOF_VALUE;
0896:                char datum = data[index];
0897:                if (datum >= BEGIN_GROUP_SHORT
0898:                        && datum <= BEGIN_GROUP_SHORT
0899:                                + BEGIN_GROUP_SHORT_INDEX_MAX)
0900:                    return datum - BEGIN_GROUP_SHORT;
0901:                else if (datum == BEGIN_GROUP_LONG
0902:                        || datum == BEGIN_ATTRIBUTE_LONG)
0903:                    return getIntN(index + 1);
0904:                return -1;
0905:            }
0906:
0907:            public String getNextTypeName(int ipos, Object xpos) {
0908:                int index = getNextTypeIndex(ipos, xpos);
0909:                return index < 0 ? null : (String) objects[index];
0910:            }
0911:
0912:            public Object getNextTypeObject(int ipos, Object xpos) {
0913:                int index = getNextTypeIndex(ipos, xpos);
0914:                return index < 0 ? null : objects[index + 1];
0915:            }
0916:
0917:            public Object getNext(int ipos, Object xpos) {
0918:                int index = ipos >>> 1;
0919:                if (index >= gapStart)
0920:                    index += gapEnd - gapStart;
0921:                if (index == data.length)
0922:                    return Sequence.eofValue;
0923:                char datum = data[index];
0924:                if (datum <= MAX_CHAR_SHORT)
0925:                    return Convert.toObject(datum);
0926:                if (datum >= OBJECT_REF_SHORT
0927:                        && datum <= OBJECT_REF_SHORT
0928:                                + OBJECT_REF_SHORT_INDEX_MAX)
0929:                    return objects[datum - OBJECT_REF_SHORT];
0930:                if (datum >= BEGIN_GROUP_SHORT
0931:                        && datum <= BEGIN_GROUP_SHORT
0932:                                + BEGIN_GROUP_SHORT_INDEX_MAX)
0933:                    return new TreeList(this , index, index + data[index + 1]
0934:                            + 2);
0935:                /*
0936:                if ((datum & 0xFF00) == BYTE_PREFIX)
0937:                  return Sequence.TEXT_BYTE_VALUE;
0938:                 */
0939:                if (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
0940:                        && datum <= INT_SHORT_ZERO + MAX_INT_SHORT)
0941:                    return Convert.toObject(datum - INT_SHORT_ZERO);
0942:                switch (datum) {
0943:                case BEGIN_DOCUMENT:
0944:                    return this ; // ???
0945:                case BOOL_FALSE:
0946:                case BOOL_TRUE:
0947:                    return Convert.toObject(datum != BOOL_FALSE);
0948:                case INT_FOLLOWS:
0949:                    return Convert.toObject(getIntN(index + 1));
0950:                case LONG_FOLLOWS:
0951:                    return Convert.toObject(getLongN(index + 1));
0952:                case FLOAT_FOLLOWS:
0953:                    return Convert.toObject(Float
0954:                            .intBitsToFloat(getIntN(index + 1)));
0955:                case DOUBLE_FOLLOWS:
0956:                    return Convert.toObject(Double
0957:                            .longBitsToDouble(getLongN(index + 1)));
0958:                case CHAR_FOLLOWS:
0959:                    return Convert.toObject(data[index + 1]);
0960:                    /*
0961:                      case CHAR_PAIR_FOLLOWS:
0962:                    return Sequence.CHAR_VALUE;
0963:                     */
0964:                case BEGIN_ATTRIBUTE_LONG: {
0965:                    int end_offset = getIntN(index + 3);
0966:                    end_offset += end_offset < 0 ? data.length : index;
0967:                    return new TreeList(this , index, end_offset + 1);
0968:                }
0969:                case BEGIN_GROUP_LONG: {
0970:                    int end_offset = getIntN(index + 1);
0971:                    end_offset += end_offset < 0 ? data.length : index;
0972:                    return new TreeList(this , index, end_offset + 7);
0973:                }
0974:                case END_GROUP_SHORT:
0975:                case END_GROUP_LONG:
0976:                case END_ATTRIBUTE:
0977:                    return Sequence.eofValue;
0978:                case POSITION_REF_FOLLOWS:
0979:                case OBJECT_REF_FOLLOWS:
0980:                    return objects[getIntN(index + 1)];
0981:                case POSITION_TRIPLE_FOLLOWS: //FIXME
0982:                    AbstractSequence seq = (AbstractSequence) objects[getIntN(index + 1)];
0983:                    ipos = getIntN(index + 3);
0984:                    int xpos_index = getIntN(index + 5);
0985:                    xpos = xpos_index < 0 ? null : objects[xpos_index];
0986:                    return SeqPosition.make(seq, ipos, xpos);
0987:                default:
0988:                    throw unsupported("getNext, code="
0989:                            + Integer.toHexString(datum));
0990:                }
0991:            }
0992:
0993:            public int stringValue(int index, StringBuffer sbuf) {
0994:                return stringValue(false, index, sbuf);
0995:            }
0996:
0997:            public int stringValue(boolean inGroup, int index, StringBuffer sbuf) {
0998:                Object value = null;
0999:                int doChildren = 0;
1000:                if (index >= gapStart)
1001:                    index += gapEnd - gapStart;
1002:                if (index == data.length)
1003:                    return -1;
1004:                char datum = data[index];
1005:                index++;
1006:                if (datum <= MAX_CHAR_SHORT) {
1007:                    sbuf.append(datum);
1008:                    return index;
1009:                }
1010:                if (datum >= OBJECT_REF_SHORT
1011:                        && datum <= OBJECT_REF_SHORT
1012:                                + OBJECT_REF_SHORT_INDEX_MAX) {
1013:                    value = objects[datum - OBJECT_REF_SHORT];
1014:                } else if (datum >= BEGIN_GROUP_SHORT
1015:                        && datum <= BEGIN_GROUP_SHORT
1016:                                + BEGIN_GROUP_SHORT_INDEX_MAX) {
1017:                    doChildren = index + 2;
1018:                    index = data[index] + index + 1;
1019:                } else if ((datum & 0xFF00) == BYTE_PREFIX) {
1020:                    sbuf.append(datum & 0xFF);
1021:                    return index;
1022:                } else if (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
1023:                        && datum <= INT_SHORT_ZERO + MAX_INT_SHORT) {
1024:                    sbuf.append((int) datum - INT_SHORT_ZERO);
1025:                    return index;
1026:                } else {
1027:                    switch (datum) {
1028:                    case BOOL_FALSE:
1029:                    case BOOL_TRUE:
1030:                        sbuf.append(datum != BOOL_FALSE);
1031:                        return index;
1032:                    case INT_FOLLOWS:
1033:                        sbuf.append(getIntN(index + 1));
1034:                        return index + 2;
1035:                    case LONG_FOLLOWS:
1036:                        sbuf.append(getLongN(index + 1));
1037:                        return index + 4;
1038:                    case FLOAT_FOLLOWS:
1039:                        sbuf.append(Float.intBitsToFloat(getIntN(index + 1)));
1040:                        return index + 2;
1041:                    case DOUBLE_FOLLOWS:
1042:                        sbuf.append(Double
1043:                                .longBitsToDouble(getLongN(index + 1)));
1044:                        return index + 4;
1045:                    case CHAR_FOLLOWS:
1046:                        sbuf.append(data[index + 1]);
1047:                        return index + 1;
1048:                    case BEGIN_DOCUMENT:
1049:                        doChildren = 1;
1050:                        index = data.length;
1051:                        break;
1052:                    case BEGIN_GROUP_LONG:
1053:                        doChildren = index + 2;
1054:                        int j = getIntN(index);
1055:                        j += j < 0 ? data.length : index - 1;
1056:                        index = j + 7;
1057:                        break;
1058:                    case END_GROUP_SHORT:
1059:                    case END_GROUP_LONG:
1060:                    case END_ATTRIBUTE:
1061:                        return -1;
1062:                    case BEGIN_ATTRIBUTE_LONG:
1063:                        if (!inGroup)
1064:                            doChildren = index + 4;
1065:                        int end = getIntN(index + 2);
1066:                        index = end + (end < 0 ? data.length + 1 : index);
1067:                        break;
1068:                    case POSITION_REF_FOLLOWS:
1069:                    case POSITION_TRIPLE_FOLLOWS:
1070:                    case OBJECT_REF_FOLLOWS:
1071:                    case CHAR_PAIR_FOLLOWS:
1072:                    default:
1073:                        throw new Error("unimplemented");
1074:                    }
1075:                }
1076:                if (value != null)
1077:                    sbuf.append(value);
1078:                if (doChildren > 0) {
1079:                    do {
1080:                        doChildren = stringValue(true, doChildren, sbuf);
1081:                    } while (doChildren >= 0);
1082:                }
1083:                return index;
1084:            }
1085:
1086:            protected void makeRelativePosition(int istart, Object xstart,
1087:                    int offset, boolean isAfter, PositionContainer posSet,
1088:                    int posNumber) {
1089:                if (offset < 0)
1090:                    throw unsupported("backwards makeRelativePostion");
1091:                int pos = istart >>> 1;
1092:                while (--offset >= 0) {
1093:                    pos = nextDataIndex(pos);
1094:                    if (pos < 0)
1095:                        throw new IndexOutOfBoundsException();
1096:                }
1097:                posSet.setPosition(posNumber, (pos << 1) | (isAfter ? 1 : 0),
1098:                        null);
1099:            }
1100:
1101:            public int nextDataIndex(int pos) {
1102:                if (pos == gapStart)
1103:                    pos = gapEnd;
1104:                if (pos == data.length)
1105:                    return -1;
1106:                int j;
1107:                char datum = data[pos++];
1108:                if (datum <= MAX_CHAR_SHORT
1109:                        || (datum >= OBJECT_REF_SHORT && datum <= OBJECT_REF_SHORT
1110:                                + OBJECT_REF_SHORT_INDEX_MAX)
1111:                        || (datum >= INT_SHORT_ZERO + MIN_INT_SHORT && datum <= INT_SHORT_ZERO
1112:                                + MAX_INT_SHORT))
1113:                    return pos;
1114:                if (datum >= BEGIN_GROUP_SHORT
1115:                        && datum <= BEGIN_GROUP_SHORT
1116:                                + BEGIN_GROUP_SHORT_INDEX_MAX)
1117:                    return data[pos] + pos + 1;
1118:                switch (datum) {
1119:                case BEGIN_DOCUMENT:
1120:                    return data.length;
1121:                case BOOL_FALSE:
1122:                case BOOL_TRUE:
1123:                    return pos;
1124:                case CHAR_FOLLOWS:
1125:                    return pos + 1;
1126:                case POSITION_REF_FOLLOWS:
1127:                case OBJECT_REF_FOLLOWS:
1128:                case CHAR_PAIR_FOLLOWS:
1129:                case INT_FOLLOWS:
1130:                    return pos + 2;
1131:                case POSITION_TRIPLE_FOLLOWS:
1132:                    return pos + 6;
1133:                case END_GROUP_SHORT:
1134:                case END_GROUP_LONG:
1135:                case END_ATTRIBUTE:
1136:                    return -1;
1137:                case BEGIN_GROUP_LONG:
1138:                    j = getIntN(pos);
1139:                    j += j < 0 ? data.length : pos - 1;
1140:                    return j + 7;
1141:                case BEGIN_ATTRIBUTE_LONG:
1142:                    j = getIntN(pos + 2);
1143:                    j += j < 0 ? data.length : pos - 1;
1144:                    return j + 1;
1145:                case LONG_FOLLOWS:
1146:                case DOUBLE_FOLLOWS:
1147:                    return pos + 4;
1148:                default:
1149:                    throw new Error("unknown code:" + (int) datum);
1150:                }
1151:            }
1152:
1153:            public void consume(Consumer out) {
1154:                consumeRange(0, data.length, out);
1155:            }
1156:
1157:            // /* DEBUGGING
1158:            public void dump() {
1159:                java.io.PrintWriter out = new java.io.PrintWriter(System.out);
1160:                dump(out);
1161:                out.flush();
1162:            }
1163:
1164:            public void dump(java.io.PrintWriter out) {
1165:                out.println("TreeList @" + System.identityHashCode(this )
1166:                        + " gapStart:" + gapStart + " gapEnd:" + gapEnd
1167:                        + " length:" + data.length);
1168:                int toskip = 0;
1169:                for (int i = 0; i < data.length; i++) {
1170:
1171:                    if (i < gapStart || i >= gapEnd) {
1172:                        int j;
1173:                        long l;
1174:                        int ch = data[i];
1175:                        out.print("" + i + ": 0x" + Integer.toHexString(ch)
1176:                                + '=' + ((short) ch));
1177:                        if (--toskip < 0) {
1178:                            if (ch <= MAX_CHAR_SHORT) {
1179:                                if (ch >= ' ' && ch < 127)
1180:                                    out.print("='" + ((char) ch) + "'");
1181:                                else if (ch == '\n')
1182:                                    out.print("='\\n'");
1183:                                else
1184:                                    out.print("='\\u" + Integer.toHexString(ch)
1185:                                            + "'");
1186:                            } else if (ch >= OBJECT_REF_SHORT
1187:                                    && ch <= OBJECT_REF_SHORT
1188:                                            + OBJECT_REF_SHORT_INDEX_MAX) {
1189:                                ch = ch - OBJECT_REF_SHORT;
1190:                                Object obj = objects[ch];
1191:                                out.print("=Object#" + ((int) ch) + '=' + obj
1192:                                        + ':' + obj.getClass().getName());
1193:                            } else if (ch >= BEGIN_GROUP_SHORT
1194:                                    && ch <= BEGIN_GROUP_SHORT
1195:                                            + BEGIN_GROUP_SHORT_INDEX_MAX) {
1196:                                ch = ch - BEGIN_GROUP_SHORT;
1197:                                out.print("=BEGIN_GROUP_SHORT index#"
1198:                                        + ((int) ch) + "=<" + objects[ch]
1199:                                        + "::" + objects[ch + 1] + '>');
1200:                                toskip = 2;
1201:                            } else if (ch >= INT_SHORT_ZERO + MIN_INT_SHORT
1202:                                    && ch <= INT_SHORT_ZERO + MAX_INT_SHORT) {
1203:                                out.print("= INT_SHORT:"
1204:                                        + (ch - INT_SHORT_ZERO));
1205:                            } else {
1206:                                switch (ch) {
1207:                                case INT_FOLLOWS:
1208:                                    j = getIntN(i + 1);
1209:                                    out.print("=INT_FOLLOWS value:" + j);
1210:                                    toskip = 2;
1211:                                    break;
1212:                                case LONG_FOLLOWS:
1213:                                    l = getLongN(i + 1);
1214:                                    out.print("=LONG_FOLLOWS value:" + l);
1215:                                    toskip = 4;
1216:                                    break;
1217:                                case FLOAT_FOLLOWS:
1218:                                    j = getIntN(i + 1);
1219:                                    out.print("=FLOAT_FOLLOWS value:"
1220:                                            + Float.intBitsToFloat(j));
1221:                                    toskip = 2;
1222:                                    break;
1223:                                case DOUBLE_FOLLOWS:
1224:                                    l = getLongN(i + 1);
1225:                                    out.print("=DOUBLE_FOLLOWS value:"
1226:                                            + Double.longBitsToDouble(l));
1227:                                    toskip = 4;
1228:                                    break;
1229:                                case BEGIN_DOCUMENT:
1230:                                    out.print("=BEGIN_DOCUMENT");
1231:                                    break;
1232:                                case BOOL_FALSE:
1233:                                    out.print("= false");
1234:                                    break;
1235:                                case BOOL_TRUE:
1236:                                    out.print("= true");
1237:                                    break;
1238:                                case CHAR_FOLLOWS:
1239:                                    out.print("=CHAR_FOLLOWS");
1240:                                    toskip = 1;
1241:                                    break;
1242:                                case CHAR_PAIR_FOLLOWS:
1243:                                    out.print("=CHAR_PAIR_FOLLOWS");
1244:                                    toskip = 2;
1245:                                    break;
1246:                                case POSITION_REF_FOLLOWS:
1247:                                case OBJECT_REF_FOLLOWS:
1248:                                    toskip = 2;
1249:                                    break;
1250:                                case END_GROUP_SHORT:
1251:                                    out.print("=END_GROUP_SHORT begin:");
1252:                                    j = i - data[i + 1];
1253:                                    out.print(j);
1254:                                    j = data[j] - BEGIN_GROUP_SHORT;
1255:                                    out.print(" -> #" + j + "=<" + objects[j]
1256:                                            + '>');
1257:                                    toskip = 1;
1258:                                    break;
1259:                                case BEGIN_GROUP_LONG:
1260:                                    j = getIntN(i + 1);
1261:                                    j += j < 0 ? data.length : i;
1262:                                    out.print("=BEGIN_GROUP_LONG end:" + j);
1263:                                    j = getIntN(j + 1);
1264:                                    out.print(" -> #" + j + "=<" + objects[j]
1265:                                            + "::" + objects[j + 1] + '>');
1266:                                    toskip = 2;
1267:                                    break;
1268:                                case END_GROUP_LONG:
1269:                                    j = getIntN(i + 1);
1270:                                    out.print("=END_GROUP_LONG name:" + j
1271:                                            + "=<" + objects[j] + '>');
1272:                                    j = getIntN(i + 3);
1273:                                    j = j < 0 ? i + j : j;
1274:                                    out.print(" begin:" + j);
1275:                                    j = getIntN(i + 5);
1276:                                    j = j < 0 ? i + j : j;
1277:                                    out.print(" parent:" + j);
1278:                                    toskip = 6;
1279:                                    break;
1280:                                case BEGIN_ATTRIBUTE_LONG:
1281:                                    j = getIntN(i + 1);
1282:                                    out.print("=BEGIN_ATTRIBUTE name:" + j
1283:                                            + "=" + objects[j]);
1284:                                    j = getIntN(i + 3);
1285:                                    j += j < 0 ? data.length : i;
1286:                                    out.print(" end:" + j);
1287:                                    toskip = 4;
1288:                                    break;
1289:                                case END_ATTRIBUTE:
1290:                                    out.print("=END_ATTRIBUTE");
1291:                                    break;
1292:                                case POSITION_TRIPLE_FOLLOWS:
1293:                                    out.print("=POSITION_TRIPLE_FOLLOWS seq:");
1294:                                    {
1295:                                        j = getIntN(i + 1);
1296:                                        out.print(j);
1297:                                        out.print("=@");
1298:                                        Object seq = objects[j];
1299:                                        if (seq == null)
1300:                                            out.print("null");
1301:                                        else
1302:                                            out.print(System
1303:                                                    .identityHashCode(seq));
1304:                                        out.print(" ipos:");
1305:                                        out.print(getIntN(i + 3));
1306:                                        out.print(" xpos:");
1307:                                        out.print(getIntN(i + 5));
1308:                                    }
1309:                                    toskip = 6;
1310:                                    /*
1311:                                    AbstractSequence seq = (AbstractSequence) objects[getIntN(i+1)];
1312:                                    ipos = getIntN(i+3);
1313:                                    int xpos_index = getIntN(i+5);
1314:                                    xpos = xpos_index < 0 ? null : objects[xpos_index];
1315:                                     */
1316:                                    break;
1317:                                }
1318:                            }
1319:                        }
1320:                        out.println();
1321:                        if (false && toskip > 0) {
1322:                            i += toskip;
1323:                            toskip = 0;
1324:                        }
1325:                    }
1326:                }
1327:            }
1328:            // DEBUGGING */
1329:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.