TreeList.java 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564
  1. // Copyright (c) 2001, 2002, 2003, 2006 Per M.A. Bothner and Brainfood Inc.
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.lists;
  4. import gnu.text.Char;
  5. /** A compact representation of a tree, that is a nested list structure.
  6. * The data structure can store anything that can be emitted to a Consumer.
  7. * This data structure is optimized for efficient forwards traversal
  8. * through the data structure, not random access.
  9. * It does have an "insertion point"; insertions and deletions are
  10. * efficient through the use of a buffer gap.
  11. * It is a reasonable choice for a "DOM" for XML data.
  12. */
  13. public class TreeList extends AbstractSequence<Object>
  14. implements
  15. /* #ifdef JAVA5 */
  16. Appendable,
  17. /* #endif */
  18. XConsumer, PositionConsumer, Consumable
  19. {
  20. // Some public fields and methods are public which probably shouldn't be,
  21. // for the sake of XMLFilter. FIXME. Perhaps an abstract class
  22. // in gnu.lists that XMLFilter extend?
  23. public Object[] objects;
  24. public int oindex;
  25. public char[] data;
  26. public int gapStart;
  27. public int gapEnd;
  28. /** If non-zero, gap is in an attribute starting (1 less than) here. */
  29. public int attrStart;
  30. /** If non-zero, gap is in an document starting (1 less than) here. */
  31. public int docStart;
  32. public TreeList()
  33. {
  34. reserveObjects(20);
  35. gapEnd = 200;
  36. data = new char[gapEnd];
  37. }
  38. /**
  39. * Make a copy of a sub-range of a TreeList.
  40. * @param list the TreeList to copy
  41. * @param startPosition start of range, as a raw index in data
  42. * @param endPosition end of range, as a raw index in data
  43. */
  44. public TreeList(TreeList list, int startPosition, int endPosition)
  45. {
  46. this();
  47. list.consumeIRange(startPosition, endPosition, this);
  48. }
  49. public TreeList(TreeList list)
  50. {
  51. this(list, 0, list.data.length);
  52. }
  53. public void clear()
  54. {
  55. gapStart = 0;
  56. gapEnd = data.length;
  57. attrStart = 0;
  58. if (gapEnd > 1500)
  59. {
  60. gapEnd = 200;
  61. data = new char[gapEnd];
  62. }
  63. objects = null;
  64. oindex = 0;
  65. reserveObjects(0);
  66. }
  67. // The data array contains an encoding of values, as follows:
  68. // 0x0000 ... 0x9FFF: A single Unicode character.
  69. // 0xAXXX: BEGIN_ELEMENT_SHORT
  70. // 0xBXXX: negative integer ((short)0x0XXX<<4)>>4, range -4096 to -1
  71. // 0xCXXX: positive integer 0x0XXX, in the range 0 to 4095
  72. // 0xDXXX: positive integer 0x1XXX, in the range 4096 to 8191
  73. // 0xEXXX:: OBJECT_REF_SHORT. The object in objects[0xXXX].
  74. // 0xF0XX: A byte (encoded character or char fragment) ((byte) 0xXX).
  75. // 0xF100 ... 0xF101: A Boolean (BOOL_FALSE, BOOL_TRUE)
  76. // 0xF102 A B: INT_FOLLOWS - 32-bit int (big-endian)
  77. // 0xF103 A B C D: LONG_FOLLOWS 64-bit long int (big-endian)
  78. // 0xF104 A B: FLOAT_FOLLOWS 32-bit float (big-endian)
  79. // 0xF105 A B C D: DOUBLE_FOLLOWS 64-bit double (big-endian)
  80. // 0xF106: CHAR_FOLLOWS
  81. // 0xF108: BEGIN_ELEMENT_LONG
  82. // 0xF109: BEGIN_ATTRIBUTE_LONG
  83. // 0xF10A: END_ATTRIBUTE
  84. // 0xF10B: END_ELEMENT_SHORT
  85. // 0xF10C: END_ELEMENT_LONG
  86. // 0xF10D A B: OBJECT_REF_FOLLOWS: The object in objects[(A,B)].
  87. // 0xF10E A B: POSITION_REF_FOLLOWS: The TreePosition in objects[(A,B)].
  88. // 0xF10F A B C D: POSITION_PAIR_FOLLOWS
  89. // 0xF110 BEGIN_DOCUMENT
  90. // 0xF111 END_DOCUMENT
  91. // 0xF112 BEGIN_ENTITY
  92. // 0xF113 END_ENTITY
  93. // 0xF114 PROCESSING_INSTRUCTION
  94. // 0xF115 CDATA_SECTION
  95. // 0xF116 JOINER
  96. // 0xF117 COMMENT
  97. // 0xF118 DOCUMENT_URI: Not a node, but a property of the previous document.
  98. /** The largest Unicode character that can be encoded in one char. */
  99. public static final int MAX_CHAR_SHORT = 0x9FFF;
  100. /** The smallest integer that can use the short int encoding. */
  101. static final int MIN_INT_SHORT = -0x1000; // -4096
  102. /** The largest integer that can use the short int encoding. */
  103. static final int MAX_INT_SHORT = 0x1FFF; // 8191
  104. /** The value used to encode the integer zero. */
  105. static final int INT_SHORT_ZERO = 0xC000;
  106. /** The value used to encode the object in objects[0]. */
  107. static final int OBJECT_REF_SHORT = 0xE000;
  108. /** The maximum offset in the objects array for a short object-ref. */
  109. static final int OBJECT_REF_SHORT_INDEX_MAX = 0xFFF;
  110. /** Followed by 2 chars that provide an index into objects. */
  111. static final char OBJECT_REF_FOLLOWS = 0xF10D;
  112. /** Followed by 2 chars that provide an index into objects. */
  113. static final char POSITION_REF_FOLLOWS = 0xF10E;
  114. /** A position triple referencing some other "nodes".
  115. * Followed by index of sequence (2 chars), and ipos (2 chars). */
  116. protected static final char POSITION_PAIR_FOLLOWS = 0xF10F;
  117. /** Encoding prefix that indicates a byte value. */
  118. static final int BYTE_PREFIX = 0xF000;
  119. /** The value used to encode false. */
  120. static final char BOOL_FALSE = 0xF100;
  121. /** The value used to encode true. */
  122. static final char BOOL_TRUE = 0xF101;
  123. /** A 32-bit integer, non-compact form.
  124. *
  125. * [INT_FOLLOWS]
  126. * [word1], [word2]: The big-endian bits of the integer.
  127. */
  128. public static final int INT_FOLLOWS = 0xF102;
  129. /** A 64-bit long integer.
  130. *
  131. * [LONG_FOLLOWS]
  132. * [word1], [word2], [word3], [word4]: The big-endian bits of the long.
  133. */
  134. static final int LONG_FOLLOWS = 0xF103;
  135. /** A 32-bit float floating-pointer number.
  136. *
  137. * [FLOAT_FOLLOWS]
  138. * [word1], [word2]: The big-endian bits of the float.
  139. */
  140. static final int FLOAT_FOLLOWS = 0xF104;
  141. /** A 64-bit double floating-pointer number.
  142. *
  143. * [DOUBLE_FOLLOWS]
  144. * [word1], [word2], [word3], [word4]: The big-endian bits of the double.
  145. */
  146. static final int DOUBLE_FOLLOWS = 0xF105;
  147. /** A 16-bit (non-compact) Unicode char follows. */
  148. static final int CHAR_FOLLOWS = 0xF106;
  149. /** A comment node follows.
  150. * [COMMENT]
  151. * [length] 2 shorts
  152. * [comment text], (length) number of characters.
  153. */
  154. static final int COMMENT = 0xF117;
  155. /** A processing-instruction node follows.
  156. * [PROCESSING_INSTRUCTION]
  157. * [target] 2 shorts, where objects[target] is the target as a String.
  158. * [length] 2 shorts.
  159. * [comment text], (length) number of characters.
  160. */
  161. protected static final int PROCESSING_INSTRUCTION = 0xF114;
  162. /** A CDATA node follows.
  163. * [CDATA_SECTION]
  164. * [length] 2 shorts
  165. * [comment text], (length) number of characters.
  166. */
  167. static final int CDATA_SECTION = 0xF115;
  168. /** Suppress spacing between non-node items. */
  169. static final int JOINER = 0xF116;
  170. /** The beginning of an attribute.
  171. * [BEGIN_ATTRIBUTE_LONG]
  172. * [index], 2 shorts, where objects[index] is the attribute type name
  173. * and objects[index+1] is the attribute type object.
  174. * [end_offset], 2 shorts, giving the location of the following
  175. * END_ATTRIBUTE. If the attribute straddles the gap, then
  176. * end_offset is a negative offset relative to data.length.
  177. * (Therefore allocating more space for the gap does not require
  178. * adjusting end_offset.) Otherwise, the end_offset is relative
  179. * to the BEGIN_ATTRIBUTE_LONG word.
  180. */
  181. protected static final int BEGIN_ATTRIBUTE_LONG = 0xF109;
  182. public static final int BEGIN_ATTRIBUTE_LONG_SIZE = 5;
  183. /** The end of an attribute of a node. */
  184. static final int END_ATTRIBUTE = 0xF10A;
  185. public static final int END_ATTRIBUTE_SIZE = 1;
  186. /** Beginning of a document (or top-level value).
  187. * Used to distinguish a document from its element node.
  188. * [end_offset], 2 shorts, giving the location of the following
  189. * END_DOCUMENT. If the attribute straddles the gap, then
  190. * end_offset is a negative offset relative to data.length.
  191. * (Therefore allocating more space for the gap does not require
  192. * adjusting end_offset.) Otherwise, the end_offset is relative
  193. * to the BEGIN_DOCUMENT word.
  194. * [parent_offset], in 2 shorts. The parent node, or -1 if no parent.
  195. * Otherwise, a negative value is a relative offset, while a non-negative
  196. * value is absolute. (Use the latter when gap is between this node and
  197. * its parent. The parent would normally be a BEGIN_ENTITY.
  198. */
  199. protected static final int BEGIN_DOCUMENT = 0xF110;
  200. /** End of a document. */
  201. protected static final int END_DOCUMENT = 0xF111;
  202. /** Start of an entity (typically a file, possibly included).
  203. * [base_uri], 2 shorts, given an index of a base-uri object
  204. * [parent_offset], in 2 shorts, encoded as for BEGIN_DOCUMENT.
  205. */
  206. public static final int BEGIN_ENTITY = 0xF112;
  207. public static final int BEGIN_ENTITY_SIZE = 5;
  208. protected static final int END_ENTITY = 0xF113;
  209. /** The document-uri property of a node.
  210. * This is not an actual value, but it is a property of the previous
  211. * document node, or the surrounding node just after a BEGIN_XXX entry.
  212. * [DOCUMENT_URI]
  213. * [index]. 2 shorts, where objects[index] is the document-uri value.
  214. */
  215. protected static final int DOCUMENT_URI = 0xF118;
  216. /** Beginning of an element, compact form.
  217. *
  218. * [BEGIN_ELEMENT_SHORT + index], where objects[index] is the element's
  219. * type name and objects[index+1] is the type object.
  220. * [end_offset], the unsigned offset (from the initial word)
  221. * to the corresponding END_ELEMENT_SHORT.
  222. * [parent_offset], the (unsigned absolute value of the) offset
  223. * to the outer BEGIN_ELEMENT_SHORT/BEGIN_ELEMENT_LONG/BEGIN_DOCUMENT.
  224. *. (If these is no parent, then parent_offset==0.)
  225. *
  226. * This should is used when {@code index < BEGIN_ELEMENT_SHORT_INDEX_MAX},
  227. * both end_offset and parent_offset fit in 16 bits,
  228. * and the element does not straddle the gap.
  229. */
  230. protected static final int BEGIN_ELEMENT_SHORT = 0xA000;
  231. protected static final int BEGIN_ELEMENT_SHORT_INDEX_MAX = 0xFFF;
  232. /** End of an element, compact form.
  233. *
  234. * [END_ELEMENT_SHORT]
  235. * [begin_offset], the unsigned absolute value of the offset to the
  236. * matching BEGIN. (This is the same as the matching end_offset.)
  237. *
  238. */
  239. protected static final int END_ELEMENT_SHORT = 0xF10B;
  240. /** Begin of an element, non-compact form.
  241. *
  242. * [BEGIN_ELEMENT_LONG]
  243. * [end_offset], in 2 shorts. The position of the matching END_ELEMENT_LONG.
  244. * If the element straddles the gap, then end_offset is a negative offset
  245. * relative to data.length. (Therefore allocating more space for the
  246. * gap does not require adjusting any end_offset.) If the element and
  247. * and its children are all on the same side of the gap, then end_offset
  248. * is a positive offset relative to the BEGIN_ELEMENT_LONG word. (Hence
  249. * shifting an entire element when the gap is moved does not require
  250. * changing its end_offset.)
  251. *
  252. * Note that the space taken by a BEGIN_ELEMENT_LONG is the same that
  253. * needed for a BEGIN_ELEMENT_SHORT (but a END_ELEMENT_LONG takes much
  254. * more space than a END_ELEMENT_SHORT). This is to make it easier
  255. * to convert a BEGIN_ELEMENT_LONG to a BEGIN_ELEMENT_SHORT or vice
  256. * versa, as needed.
  257. */
  258. protected static final int BEGIN_ELEMENT_LONG = 0xF108;
  259. /** End of n element, non-compact form.
  260. *
  261. * [END_ELEMENT_LONG]
  262. * [index], 2 shorts where objects[index] is the element's type name and
  263. * objects[index+1] is the type object.
  264. * [begin_offset], in 2 shorts. The position of the matching
  265. * BEGIN_ELEMENT_LONG. If the element straddles the gap, then begin_offset
  266. * is the actual index (i.e. relative to the start of data) of the
  267. * matching BEGIN_ELEMENT_LONG. (Therefore allocating more space for the
  268. * gap does not require adjusting begin_offset.) If the element does not
  269. * straddle the gap, then begin_offset is a negative offset relative
  270. * to the END_ELEMENT_LONG word. (Hence shifting an entire element when
  271. * the gap is moved does not require changing its begin_offset.)
  272. * relative to data.length.
  273. * [parent_offset], in 2 shorts. The position of the outer BEGIN_ELEMENT_LONG,
  274. * BEGIN_ELEMENT_SHORT or BEGIN_DOCUMENT. If the difference straddles
  275. * the gap (i.e. either this element straddles the gap or the parent element
  276. * does and the gap precedes this element), then parent_offset is the
  277. * actual index of the parent element. Otherwise, then parent_offset is a
  278. * negative offset relative to the END_ELEMENT_LONG word.
  279. */
  280. protected static final int END_ELEMENT_LONG = 0xF10C;
  281. int currentParent = -1;
  282. public void ensureSpace(int needed)
  283. {
  284. int avail = gapEnd - gapStart;
  285. if (needed > avail)
  286. {
  287. int oldSize = data.length;
  288. int neededSize = oldSize - avail + needed;
  289. int newSize = 2 * oldSize;
  290. if (newSize < neededSize)
  291. newSize = neededSize;
  292. char[] tmp = new char[newSize];
  293. if (gapStart > 0)
  294. System.arraycopy(data, 0, tmp, 0, gapStart);
  295. int afterGap = oldSize - gapEnd;
  296. if (afterGap > 0)
  297. System.arraycopy(data, gapEnd, tmp, newSize - afterGap, afterGap);
  298. gapEnd = newSize - afterGap;
  299. data = tmp;
  300. }
  301. }
  302. public final void reserveObjects(int needed) {
  303. int newLength;
  304. Object[] tmp;
  305. if (objects == null) {
  306. newLength = needed > 100 ? needed : 100;
  307. tmp = new Object[newLength];
  308. } else {
  309. int oldLength = objects.length;
  310. if (oldLength < oindex + needed) {
  311. int grow = oldLength >> 1;
  312. if (needed > grow)
  313. grow = needed;
  314. newLength = oldLength + grow;
  315. } else if (oldLength > 2 * (oindex + needed) + 100) {
  316. newLength = oindex + needed + 100;
  317. }
  318. else
  319. return;
  320. tmp = new Object[newLength];
  321. System.arraycopy(objects, 0, tmp, 0, oindex);
  322. }
  323. objects = tmp;
  324. }
  325. public int find (Object arg1)
  326. {
  327. if (oindex == objects.length)
  328. reserveObjects(1);
  329. objects[oindex] = arg1;
  330. return oindex++;
  331. }
  332. /** Get a 32-bit int from the data array. */
  333. final protected int getIntN(int index)
  334. {
  335. return (data[index] << 16) | (data[index + 1] & 0xFFFF);
  336. }
  337. /** Get a 64-bit long from the data array. */
  338. final protected long getLongN(int index)
  339. {
  340. char[] data = this.data; // Optimization.
  341. return (data[index] & 0xFFFFL) << 48
  342. | (data[index+1] & 0xFFFFL) << 32
  343. | (data[index+2] & 0xFFFFL) << 16
  344. | (data[index+3] & 0xFFFFL);
  345. }
  346. final public void setIntN(int index, int i)
  347. {
  348. data[index] = (char) (i >> 16);
  349. data[index+1] = (char) i;
  350. }
  351. public void writePosition(SeqPosition position)
  352. {
  353. ensureSpace(3);
  354. // FIXME - no need for find to search in this case!
  355. int index = find(position.copy());
  356. data[gapStart++] = POSITION_REF_FOLLOWS;
  357. setIntN(gapStart, index);
  358. gapStart += 2;
  359. }
  360. public void writePosition(AbstractSequence seq, int ipos)
  361. {
  362. ensureSpace(5);
  363. data[gapStart] = POSITION_PAIR_FOLLOWS;
  364. int seq_index = find(seq);
  365. setIntN(gapStart+1, seq_index);
  366. setIntN(gapStart+3, ipos);
  367. gapStart += 5;
  368. }
  369. public void writeObject(Object v)
  370. {
  371. if (gapEnd - gapStart < 3)
  372. ensureSpace(3);
  373. int index = find(v);
  374. if (index < 0x1000)
  375. data[gapStart++] = (char) (OBJECT_REF_SHORT | index);
  376. else
  377. {
  378. data[gapStart++] = OBJECT_REF_FOLLOWS;
  379. setIntN(gapStart, index);
  380. gapStart += 2;
  381. }
  382. }
  383. /** Write/set the document-uri property of the current document.
  384. * Only allowed immediately following startDocument. */
  385. public void writeDocumentUri (Object uri)
  386. {
  387. ensureSpace(3);
  388. int index = find(uri);
  389. data[gapStart++] = DOCUMENT_URI;
  390. setIntN(gapStart, index);
  391. gapStart += 2;
  392. }
  393. public void writeComment(char[] chars, int offset, int length)
  394. {
  395. ensureSpace(3+length);
  396. int i = gapStart;
  397. data[i++] = COMMENT;
  398. setIntN(i, length);
  399. i += 2;
  400. System.arraycopy(chars, offset, data, i, length);
  401. gapStart = i + length;
  402. }
  403. public void writeComment(String comment, int offset, int length)
  404. {
  405. ensureSpace(3+length);
  406. int i = gapStart;
  407. data[i++] = COMMENT;
  408. setIntN(i, length);
  409. i += 2;
  410. comment.getChars(offset, offset+length, data, i);
  411. gapStart = i + length;
  412. }
  413. public void writeProcessingInstruction(String target, char[] content,
  414. int offset, int length)
  415. {
  416. ensureSpace(5+length);
  417. int i = gapStart;
  418. data[i++] = PROCESSING_INSTRUCTION;
  419. int index = find(target);
  420. setIntN(i, index);
  421. setIntN(i+2, length);
  422. i += 4;
  423. System.arraycopy(content, offset, data, i, length);
  424. gapStart = i + length;
  425. }
  426. public void writeProcessingInstruction(String target, String content,
  427. int offset, int length)
  428. {
  429. ensureSpace(5+length);
  430. int i = gapStart;
  431. data[i++] = PROCESSING_INSTRUCTION;
  432. int index = find(target);
  433. setIntN(i, index);
  434. setIntN(i+2, length);
  435. i += 4;
  436. content.getChars(offset, offset+length, data, i);
  437. gapStart = i + length;
  438. }
  439. public void startElement (Object type)
  440. {
  441. startElement(find(type));
  442. }
  443. public void startDocument ()
  444. {
  445. ensureSpace(5+1);
  446. gapEnd--;
  447. int p = gapStart;
  448. data[p] = BEGIN_DOCUMENT;
  449. if (docStart != 0)
  450. throw new Error("nested document");
  451. docStart = p+1;
  452. setIntN(p+1, gapEnd - data.length);
  453. setIntN(p+3, currentParent == -1 ? -1 : currentParent-p); // parent_offset
  454. currentParent = p;
  455. gapStart = p + 5;
  456. currentParent = p;
  457. data[gapEnd] = END_DOCUMENT;
  458. }
  459. public void endDocument()
  460. {
  461. if (data[gapEnd] != END_DOCUMENT || docStart <= 0
  462. || data[currentParent] != BEGIN_DOCUMENT)
  463. throw new Error("unexpected endDocument");
  464. // Move the END_DOCUMENT to before the gap.
  465. gapEnd++;
  466. setIntN(docStart, gapStart - docStart + 1);
  467. docStart = 0;
  468. data[gapStart++] = END_DOCUMENT;
  469. int parent = getIntN(currentParent+3);
  470. currentParent = parent >= -1 ? parent : currentParent + parent;
  471. }
  472. public void beginEntity (Object base)
  473. {
  474. // Ideally, we want to ignore a beginEnity if and only if it is redundant.
  475. // There are also problems in the current implementation with
  476. // nested (or maybe any non-top-level?) BEGIN_ENTITY nodes.
  477. // So for now, let's keep it simple.
  478. if (gapStart != 0)
  479. return;
  480. ensureSpace(BEGIN_ENTITY_SIZE+1);
  481. gapEnd--;
  482. int p = gapStart;
  483. data[p] = BEGIN_ENTITY;
  484. setIntN(p+1, find(base));
  485. setIntN(p+3, currentParent == -1 ? -1 : currentParent-p); // parent_offset
  486. gapStart = p + 5;
  487. currentParent = p;
  488. data[gapEnd] = END_ENTITY;
  489. }
  490. public void endEntity ()
  491. {
  492. // See comment in beginEntity.
  493. if (gapEnd + 1 != data.length || data[gapEnd] != END_ENTITY)
  494. return;
  495. if (/*data[gapEnd] != END_ENTITY || */
  496. data[currentParent] != BEGIN_ENTITY)
  497. throw new Error("unexpected endEntity");
  498. // Move the END_ENTITY to before the gap.
  499. gapEnd++;
  500. data[gapStart++] = END_ENTITY;
  501. int parent = getIntN(currentParent+3);
  502. currentParent = parent >= -1 ? parent : currentParent + parent;
  503. }
  504. public void startElement(int index)
  505. {
  506. ensureSpace(3 + 7);
  507. gapEnd -= 7;
  508. data[gapStart++] = BEGIN_ELEMENT_LONG;
  509. setIntN(gapStart, gapEnd - data.length); // end_offset
  510. gapStart += 2;
  511. data[gapEnd] = END_ELEMENT_LONG;
  512. setIntN(gapEnd + 1, index); // begin_offset
  513. setIntN(gapEnd + 3, gapStart - 3); // begin_offset
  514. setIntN(gapEnd + 5, currentParent); // parent_offset
  515. currentParent = gapStart - 3;
  516. }
  517. public void setElementName (int elementIndex, int nameIndex)
  518. {
  519. if (data[elementIndex] == BEGIN_ELEMENT_LONG)
  520. {
  521. int j = getIntN(elementIndex+1);
  522. elementIndex = j + (j < 0 ? data.length : elementIndex);
  523. }
  524. if (elementIndex < gapEnd)
  525. throw new Error("setElementName before gapEnd");
  526. setIntN(elementIndex + 1, nameIndex);
  527. }
  528. public void endElement ()
  529. {
  530. if (data[gapEnd] != END_ELEMENT_LONG)
  531. throw new Error("unexpected endElement");
  532. int index = getIntN(gapEnd + 1);
  533. int begin = getIntN(gapEnd + 3);
  534. int parent = getIntN(gapEnd + 5);
  535. currentParent = parent;
  536. gapEnd += 7;
  537. int offset = gapStart - begin;
  538. int parentOffset = begin - parent;
  539. if (index < BEGIN_ELEMENT_SHORT_INDEX_MAX
  540. && offset < 0x10000 && parentOffset < 0x10000)
  541. {
  542. data[begin] = (char) (BEGIN_ELEMENT_SHORT | index);
  543. data[begin + 1] = (char) offset; // end_offset
  544. data[begin + 2] = (char) parentOffset;
  545. data[gapStart] = END_ELEMENT_SHORT;
  546. data[gapStart + 1] = (char) offset; // begin_offset
  547. gapStart += 2;
  548. }
  549. else
  550. {
  551. data[begin] = BEGIN_ELEMENT_LONG;
  552. setIntN(begin + 1, offset);
  553. data[gapStart] = END_ELEMENT_LONG;
  554. setIntN(gapStart + 1, index);
  555. setIntN(gapStart + 3, - offset);
  556. if (parent >= gapStart || begin <= gapStart)
  557. parent -= gapStart;
  558. setIntN(gapStart + 5, parent);
  559. gapStart += 7;
  560. }
  561. }
  562. public void startAttribute (Object attrType)
  563. {
  564. startAttribute(find(attrType));
  565. }
  566. public void startAttribute (int index)
  567. {
  568. /* This needs to be tested. FIXME. Anyway only solves limited problem.
  569. // If there is whitespace and nothing else between the BEGIN_ELEMENT_LONG
  570. // and the current position, get rid of the spaces.
  571. int i = currentParent;
  572. if (i > 0 && (i += 3) < gapStart)
  573. {
  574. for (int j = i; ; j++)
  575. {
  576. if (j == gapStart)
  577. {
  578. gapStart = i;
  579. break;
  580. }
  581. char c = data[j];
  582. if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
  583. break;
  584. }
  585. }
  586. */
  587. ensureSpace(5 + 1);
  588. gapEnd--;
  589. data[gapStart++] = BEGIN_ATTRIBUTE_LONG;
  590. if (attrStart != 0)
  591. throw new Error("nested attribute");
  592. attrStart = gapStart;
  593. setIntN(gapStart, index);
  594. setIntN(gapStart + 2, gapEnd - data.length);
  595. gapStart += 4;
  596. data[gapEnd] = END_ATTRIBUTE;
  597. }
  598. public void setAttributeName (int attrIndex, int nameIndex)
  599. {
  600. setIntN(attrIndex + 1, nameIndex);
  601. }
  602. public void endAttribute()
  603. {
  604. if (attrStart <= 0)
  605. return;
  606. if (data[gapEnd] != END_ATTRIBUTE)
  607. throw new Error("unexpected endAttribute");
  608. // Move the END_ATTRIBUTES to before the gap.
  609. gapEnd++;
  610. setIntN(attrStart+2, gapStart - attrStart + 1);
  611. attrStart = 0;
  612. data[gapStart++] = END_ATTRIBUTE;
  613. }
  614. public Consumer append (char c)
  615. {
  616. write(c);
  617. return this;
  618. }
  619. public void write (int c)
  620. {
  621. ensureSpace(3);
  622. if (c <= MAX_CHAR_SHORT)
  623. data[gapStart++] = (char) c;
  624. else if (c < 0x10000)
  625. {
  626. data[gapStart++] = CHAR_FOLLOWS;
  627. data[gapStart++] = (char) c;
  628. }
  629. else
  630. Char.print(c, this);
  631. }
  632. public void writeBoolean(boolean v)
  633. {
  634. ensureSpace(1);
  635. data[gapStart++] = v ? BOOL_TRUE : BOOL_FALSE;
  636. }
  637. public void writeByte(int v)
  638. {
  639. ensureSpace(1);
  640. data[gapStart++] = (char) (BYTE_PREFIX + (v & 0xFF));
  641. }
  642. public void writeInt(int v) {
  643. if (v >= MIN_INT_SHORT && v <= MAX_INT_SHORT) {
  644. ensureSpace(1);
  645. data[gapStart++] = (char) (INT_SHORT_ZERO + v);
  646. } else
  647. writeIntForce32(v);
  648. }
  649. public void writeIntForce32(int v) {
  650. ensureSpace(3);
  651. int pos = gapStart;
  652. data[pos++] = INT_FOLLOWS;
  653. setIntN(pos, v);
  654. gapStart = pos + 2;
  655. }
  656. public void writeLong(long v)
  657. {
  658. ensureSpace(5);
  659. data[gapStart++] = LONG_FOLLOWS;
  660. data[gapStart++] = (char) (v >>> 48);
  661. data[gapStart++] = (char) (v >>> 32);
  662. data[gapStart++] = (char) (v >>> 16);
  663. data[gapStart++] = (char) v;
  664. }
  665. public void writeFloat(float v)
  666. {
  667. ensureSpace(3);
  668. int i = Float.floatToIntBits(v);
  669. data[gapStart++] = FLOAT_FOLLOWS;
  670. data[gapStart++] = (char) (i >>> 16);
  671. data[gapStart++] = (char) i;
  672. }
  673. public void writeDouble(double v)
  674. {
  675. ensureSpace(5);
  676. long l = Double.doubleToLongBits(v);
  677. data[gapStart++] = DOUBLE_FOLLOWS;
  678. data[gapStart++] = (char) (l >>> 48);
  679. data[gapStart++] = (char) (l >>> 32);
  680. data[gapStart++] = (char) (l >>> 16);
  681. data[gapStart++] = (char) l;
  682. }
  683. public boolean ignoring()
  684. {
  685. return false;
  686. }
  687. public void writeJoiner ()
  688. {
  689. ensureSpace(1);
  690. data[gapStart++] = JOINER;
  691. }
  692. public void write(char[] buf, int off, int len)
  693. {
  694. if (len == 0)
  695. writeJoiner();
  696. ensureSpace(len);
  697. while (len > 0)
  698. {
  699. char ch = buf[off++];
  700. len--;
  701. if (ch <= MAX_CHAR_SHORT)
  702. data[gapStart++] = ch;
  703. else
  704. {
  705. write(ch);
  706. ensureSpace(len);
  707. }
  708. }
  709. }
  710. public void write (String str)
  711. {
  712. write(str, 0, str.length());
  713. }
  714. /* #ifdef use:java.lang.CharSequence */
  715. public void write (CharSequence str, int start, int length)
  716. /* #else */
  717. // public void write (String str, int start, int length)
  718. /* #endif */
  719. {
  720. if (length == 0)
  721. writeJoiner();
  722. ensureSpace(length);
  723. while (length > 0)
  724. {
  725. char ch = str.charAt(start++);
  726. length--;
  727. if (ch <= MAX_CHAR_SHORT)
  728. data[gapStart++] = ch;
  729. else
  730. {
  731. write(ch);
  732. ensureSpace(length);
  733. }
  734. }
  735. }
  736. public void writeCDATA (char[] chars, int offset, int length)
  737. {
  738. ensureSpace(3+length);
  739. int i = gapStart;
  740. data[i++] = CDATA_SECTION;
  741. setIntN(i, length);
  742. i += 2;
  743. System.arraycopy(chars, offset, data, i, length);
  744. gapStart = i + length;
  745. }
  746. /* #ifdef use:java.lang.CharSequence */
  747. public Consumer append (CharSequence csq)
  748. {
  749. if (csq == null)
  750. csq = "null";
  751. return append(csq, 0, csq.length());
  752. }
  753. public Consumer append (CharSequence csq, int start, int end)
  754. {
  755. if (csq == null)
  756. csq = "null";
  757. for (int i = start; i < end; i++)
  758. append(csq.charAt(i));
  759. return this;
  760. }
  761. /* #else */
  762. // public Consumer append (String str)
  763. // {
  764. // if (str == null)
  765. // str = "null";
  766. // int len = str.length();
  767. // for (int i = 0; i < len; i++)
  768. // append(str.charAt(i));
  769. // return this;
  770. // }
  771. /* #endif */
  772. public boolean isEmpty()
  773. {
  774. // FIXME does not work if we allow comment() entries!
  775. int pos = gapStart == 0 ? gapEnd : 0;
  776. return pos == data.length;
  777. }
  778. public int size()
  779. {
  780. int size = 0;
  781. int i = 0;
  782. for (;;)
  783. {
  784. i = nextPos(i);
  785. if (i == 0)
  786. return size;
  787. size++;
  788. }
  789. }
  790. public int createPos(int index, boolean isAfter)
  791. {
  792. return createRelativePos(0, index, isAfter);
  793. }
  794. public final int posToDataIndex (int ipos)
  795. {
  796. if (ipos == -1)
  797. return data.length;
  798. int index = ipos >>> 1;
  799. if ((ipos & 1) != 0)
  800. index--;
  801. if (index == gapStart)
  802. index += gapEnd - gapStart;
  803. if ((ipos & 1) != 0)
  804. {
  805. index = nextDataIndex(index);
  806. if (index < 0)
  807. return data.length;
  808. if (index == gapStart)
  809. index += gapEnd - gapStart;
  810. }
  811. return index;
  812. }
  813. public int firstChildPos (int ipos)
  814. {
  815. int index = gotoChildrenStart(posToDataIndex(ipos));
  816. if (index < 0)
  817. return 0;
  818. return index << 1;
  819. }
  820. public final int gotoChildrenStart(int index)
  821. {
  822. if (index == data.length)
  823. return -1;
  824. char datum = data[index];
  825. if ((datum >= BEGIN_ELEMENT_SHORT
  826. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  827. || datum == BEGIN_ELEMENT_LONG)
  828. index += 3;
  829. else if (datum == BEGIN_DOCUMENT || datum == BEGIN_ENTITY)
  830. index += 5;
  831. else
  832. return -1;
  833. for (;;)
  834. {
  835. if (index >= gapStart)
  836. index += gapEnd - gapStart;
  837. datum = data[index];
  838. if (datum == BEGIN_ATTRIBUTE_LONG)
  839. {
  840. int end = getIntN(index+3);
  841. index = end + (end < 0 ? data.length : index);
  842. }
  843. else if (datum == END_ATTRIBUTE || datum == JOINER)
  844. index++;
  845. else if (datum == DOCUMENT_URI)
  846. index += 3;
  847. else
  848. break;
  849. }
  850. return index;
  851. }
  852. public int parentPos (int ipos)
  853. {
  854. int index = posToDataIndex(ipos);
  855. for (;;)
  856. {
  857. index = parentOrEntityI(index);
  858. if (index == -1)
  859. return -1;
  860. if (data[index] != BEGIN_ENTITY)
  861. return index << 1;
  862. }
  863. }
  864. public int parentOrEntityPos (int ipos)
  865. {
  866. int index = parentOrEntityI(posToDataIndex(ipos));
  867. return index < 0 ? -1 : index << 1;
  868. }
  869. public int parentOrEntityI (int index)
  870. {
  871. if (index == data.length)
  872. return -1;
  873. char datum = data[index];
  874. if (datum == BEGIN_DOCUMENT || datum == BEGIN_ENTITY)
  875. {
  876. int parent_offset = getIntN(index+3);
  877. if (parent_offset >= -1)
  878. return parent_offset;
  879. else
  880. return index + parent_offset;
  881. }
  882. if (datum >= BEGIN_ELEMENT_SHORT
  883. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  884. {
  885. int parent_offset = data[index+2];
  886. return parent_offset == 0 ? -1 : index - parent_offset;
  887. }
  888. if (datum == BEGIN_ELEMENT_LONG)
  889. {
  890. int end_offset = getIntN(index+1);
  891. end_offset += end_offset < 0 ? data.length : index;
  892. int parent_offset = getIntN(end_offset+5);
  893. if (parent_offset == 0)
  894. return -1;
  895. if (parent_offset < 0)
  896. parent_offset += end_offset;
  897. return parent_offset;
  898. }
  899. for (;;)
  900. {
  901. if (index == gapStart)
  902. index = gapEnd;
  903. if (index == data.length)
  904. return -1;
  905. datum = data[index];
  906. switch (datum)
  907. {
  908. case END_ELEMENT_SHORT:
  909. return index - data[index+1];
  910. case END_ELEMENT_LONG:
  911. int begin_offset = getIntN(index+3);
  912. if (begin_offset < 0)
  913. begin_offset += index;
  914. return begin_offset;
  915. case END_ATTRIBUTE:
  916. index++;
  917. continue;
  918. case END_DOCUMENT:
  919. return -1;
  920. default:
  921. index = nextDataIndex(index);
  922. }
  923. if (index < 0)
  924. break;
  925. }
  926. return -1;
  927. }
  928. public int getAttributeCount (int parent)
  929. {
  930. int n = 0;
  931. for (int attr = firstAttributePos(parent);
  932. attr != 0 && getNextKind(attr) == Sequence.ATTRIBUTE_VALUE;
  933. attr = nextPos(attr))
  934. n++;
  935. return n;
  936. }
  937. public boolean gotoAttributesStart(TreePosition pos)
  938. {
  939. int index = gotoAttributesStart(pos.ipos >> 1);
  940. if (index < 0)
  941. return false;
  942. pos.push(this, index << 1);
  943. return true;
  944. }
  945. public int firstAttributePos (int ipos)
  946. {
  947. int index = gotoAttributesStart(posToDataIndex(ipos));
  948. return index < 0 ? 0 : index << 1;
  949. }
  950. public int gotoAttributesStart(int index)
  951. {
  952. if (index >= gapStart)
  953. index += gapEnd - gapStart;
  954. if (index == data.length)
  955. return -1;
  956. char datum = data[index];
  957. if ((datum >= BEGIN_ELEMENT_SHORT
  958. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  959. || datum == BEGIN_ELEMENT_LONG)
  960. return index + 3;
  961. else
  962. return -1;
  963. }
  964. public Object get (int index)
  965. {
  966. int i = 0;
  967. while (--index >= 0)
  968. {
  969. i = nextPos(i);
  970. if (i == 0)
  971. throw new IndexOutOfBoundsException();
  972. }
  973. return getPosNext(i);
  974. }
  975. public boolean consumeNext(int ipos, Consumer out)
  976. {
  977. if (! hasNext(ipos))
  978. return false;
  979. int start = posToDataIndex(ipos);
  980. int end = nextNodeIndex(start, -1 >>> 1);
  981. if (end == start)
  982. end = nextDataIndex(start);
  983. if (end >= 0)
  984. consumeIRange(start, end, out);
  985. return true;
  986. }
  987. public void consumePosRange(int startPos, int endPos, Consumer out)
  988. {
  989. consumeIRange(posToDataIndex(startPos), posToDataIndex(endPos), out);
  990. }
  991. public int consumeIRange(int startPosition, int endPosition, Consumer out)
  992. {
  993. int pos = startPosition;
  994. int limit = startPosition <= gapStart && endPosition > gapStart ? gapStart
  995. : endPosition;
  996. int index;
  997. for (;;)
  998. {
  999. if (pos >= limit)
  1000. {
  1001. if (pos == gapStart && endPosition > gapEnd)
  1002. {
  1003. pos = gapEnd;
  1004. limit = endPosition;
  1005. }
  1006. else
  1007. break;
  1008. }
  1009. char datum = data[pos++];
  1010. if (datum <= MAX_CHAR_SHORT)
  1011. {
  1012. int start = pos - 1;
  1013. int lim = limit;
  1014. for (;;)
  1015. {
  1016. if (pos >= lim)
  1017. break;
  1018. datum = data[pos++];
  1019. if (datum > MAX_CHAR_SHORT)
  1020. {
  1021. pos--;
  1022. break;
  1023. }
  1024. }
  1025. out.write(data, start, pos - start);
  1026. continue;
  1027. }
  1028. if (datum >= OBJECT_REF_SHORT
  1029. && datum <= OBJECT_REF_SHORT+OBJECT_REF_SHORT_INDEX_MAX)
  1030. {
  1031. out.writeObject(objects[datum-OBJECT_REF_SHORT]);
  1032. continue;
  1033. }
  1034. if (datum >= BEGIN_ELEMENT_SHORT
  1035. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  1036. {
  1037. index = datum-BEGIN_ELEMENT_SHORT;
  1038. out.startElement(objects[index]);
  1039. pos += 2;
  1040. continue;
  1041. }
  1042. /*
  1043. if ((datum & 0xFF00) == BYTE_PREFIX)
  1044. {
  1045. out.writeByte((byte) datum);
  1046. continue;
  1047. }
  1048. */
  1049. if (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
  1050. && datum <= INT_SHORT_ZERO + MAX_INT_SHORT)
  1051. {
  1052. out.writeInt(datum - INT_SHORT_ZERO);
  1053. continue;
  1054. }
  1055. switch (datum)
  1056. {
  1057. case BEGIN_DOCUMENT:
  1058. out.startDocument();
  1059. pos += 4;
  1060. continue;
  1061. case END_DOCUMENT:
  1062. out.endDocument();
  1063. continue;
  1064. case BEGIN_ENTITY:
  1065. if (out instanceof TreeList)
  1066. ((TreeList) out).beginEntity(objects[getIntN(pos)]);
  1067. pos += 4;
  1068. continue;
  1069. case END_ENTITY:
  1070. if (out instanceof TreeList)
  1071. ((TreeList) out).endEntity();
  1072. continue;
  1073. case DOCUMENT_URI:
  1074. if (out instanceof TreeList)
  1075. ((TreeList) out).writeDocumentUri(objects[getIntN(pos)]);
  1076. pos += 2;
  1077. continue;
  1078. case COMMENT:
  1079. {
  1080. int length = getIntN(pos);
  1081. pos += 2;
  1082. if (out instanceof XConsumer)
  1083. ((XConsumer) out).writeComment(data, pos, length);
  1084. pos += length;
  1085. }
  1086. continue;
  1087. case CDATA_SECTION:
  1088. {
  1089. int length = getIntN(pos);
  1090. pos += 2;
  1091. if (out instanceof XConsumer)
  1092. ((XConsumer) out).writeCDATA(data, pos, length);
  1093. else
  1094. out.write(data, pos, length);
  1095. pos += length;
  1096. }
  1097. continue;
  1098. case PROCESSING_INSTRUCTION:
  1099. {
  1100. String target = (String) objects[getIntN(pos)];
  1101. int length = getIntN(pos+2);
  1102. pos += 4;
  1103. if (out instanceof XConsumer)
  1104. ((XConsumer) out).writeProcessingInstruction(target, data,
  1105. pos, length);
  1106. pos += length;
  1107. }
  1108. continue;
  1109. case BOOL_FALSE:
  1110. case BOOL_TRUE:
  1111. out.writeBoolean(datum != BOOL_FALSE);
  1112. continue;
  1113. case JOINER:
  1114. out.write("");
  1115. continue;
  1116. case CHAR_FOLLOWS:
  1117. out.write(data, pos, 1 + datum - CHAR_FOLLOWS);
  1118. pos++;
  1119. continue;
  1120. case POSITION_PAIR_FOLLOWS:
  1121. {
  1122. AbstractSequence seq = (AbstractSequence) objects[getIntN(pos)];
  1123. int ipos = getIntN(pos+2);
  1124. if (out instanceof PositionConsumer)
  1125. ((PositionConsumer) out).writePosition(seq, ipos);
  1126. else
  1127. out.writeObject(seq.getIteratorAtPos(ipos));
  1128. pos += 4;
  1129. }
  1130. continue;
  1131. case POSITION_REF_FOLLOWS:
  1132. if (out instanceof PositionConsumer)
  1133. {
  1134. ((PositionConsumer) out).writePosition((SeqPosition) objects[getIntN(pos)]);
  1135. pos += 2;
  1136. continue;
  1137. }
  1138. // ... else fall through ...
  1139. case OBJECT_REF_FOLLOWS:
  1140. out.writeObject(objects[getIntN(pos)]);
  1141. pos += 2;
  1142. continue;
  1143. case END_ELEMENT_SHORT:
  1144. pos++;
  1145. out.endElement();
  1146. continue;
  1147. case BEGIN_ELEMENT_LONG:
  1148. index = getIntN(pos);
  1149. index += index >= 0 ? pos - 1 : data.length;
  1150. pos += 2;
  1151. index = getIntN(index + 1);
  1152. out.startElement(objects[index]);
  1153. continue;
  1154. case END_ELEMENT_LONG:
  1155. index = getIntN(pos);
  1156. out.endElement();
  1157. pos += 6;
  1158. continue;
  1159. case BEGIN_ATTRIBUTE_LONG:
  1160. index = getIntN(pos);
  1161. out.startAttribute(objects[index]);
  1162. pos += 4;
  1163. continue;
  1164. case END_ATTRIBUTE:
  1165. out.endAttribute();
  1166. continue;
  1167. case INT_FOLLOWS:
  1168. out.writeInt(getIntN(pos));
  1169. pos += 2;
  1170. continue;
  1171. case FLOAT_FOLLOWS:
  1172. out.writeFloat(Float.intBitsToFloat(getIntN(pos)));
  1173. pos += 2;
  1174. continue;
  1175. case LONG_FOLLOWS:
  1176. out.writeLong(getLongN(pos));
  1177. pos += 4;
  1178. continue;
  1179. case DOUBLE_FOLLOWS:
  1180. out.writeDouble(Double.longBitsToDouble(getLongN(pos)));
  1181. pos += 4;
  1182. continue;
  1183. default:
  1184. throw new Error("unknown code:"+(int) datum);
  1185. }
  1186. }
  1187. return pos;
  1188. }
  1189. public void toString (String sep, StringBuffer sbuf)
  1190. {
  1191. int pos = 0;
  1192. int limit = gapStart;
  1193. int index;
  1194. boolean seen = false;
  1195. boolean inStartTag = false;
  1196. boolean inAttribute = false;
  1197. for (;;)
  1198. {
  1199. if (pos >= limit)
  1200. {
  1201. if (pos == gapStart)
  1202. {
  1203. pos = gapEnd;
  1204. limit = data.length;
  1205. if (pos == limit)
  1206. break;
  1207. }
  1208. else
  1209. break;
  1210. }
  1211. char datum = data[pos++];
  1212. if (datum <= MAX_CHAR_SHORT)
  1213. {
  1214. int start = pos - 1;
  1215. int lim = limit;
  1216. for (;;)
  1217. {
  1218. if (pos >= lim)
  1219. break;
  1220. datum = data[pos++];
  1221. if (datum > MAX_CHAR_SHORT)
  1222. {
  1223. pos--;
  1224. break;
  1225. }
  1226. }
  1227. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1228. sbuf.append(data, start, pos - start);
  1229. seen = false;
  1230. continue;
  1231. }
  1232. if (datum >= OBJECT_REF_SHORT
  1233. && datum <= OBJECT_REF_SHORT+OBJECT_REF_SHORT_INDEX_MAX)
  1234. {
  1235. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1236. if (seen) sbuf.append(sep); else seen = true;
  1237. sbuf.append(objects[datum-OBJECT_REF_SHORT]);
  1238. continue;
  1239. }
  1240. if (datum >= BEGIN_ELEMENT_SHORT
  1241. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  1242. {
  1243. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1244. index = datum-BEGIN_ELEMENT_SHORT;
  1245. if (seen) sbuf.append(sep);
  1246. sbuf.append('<');
  1247. sbuf.append(objects[index].toString());
  1248. pos += 2;
  1249. seen = false;
  1250. inStartTag = true;
  1251. continue;
  1252. }
  1253. if (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
  1254. && datum <= INT_SHORT_ZERO + MAX_INT_SHORT)
  1255. {
  1256. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1257. if (seen) sbuf.append(sep); else seen = true;
  1258. sbuf.append(datum - INT_SHORT_ZERO);
  1259. continue;
  1260. }
  1261. switch (datum)
  1262. {
  1263. case BEGIN_DOCUMENT:
  1264. case BEGIN_ENTITY:
  1265. pos += 4;
  1266. continue;
  1267. case DOCUMENT_URI:
  1268. pos += 2;
  1269. continue;
  1270. case COMMENT:
  1271. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1272. index = getIntN(pos); // comment length
  1273. pos += 2;
  1274. sbuf.append("<!--");
  1275. sbuf.append(data, pos, index);
  1276. sbuf.append("-->");
  1277. pos += index;
  1278. continue;
  1279. case CDATA_SECTION:
  1280. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1281. index = getIntN(pos); // comment length
  1282. pos += 2;
  1283. sbuf.append("<![CDATA[");
  1284. sbuf.append(data, pos, index);
  1285. sbuf.append("]]>");
  1286. pos += index;
  1287. continue;
  1288. case PROCESSING_INSTRUCTION:
  1289. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1290. sbuf.append("<?");
  1291. index = getIntN(pos); // target
  1292. pos += 2;
  1293. sbuf.append(objects[index]);
  1294. index = getIntN(pos); // comment length
  1295. pos += 2;
  1296. if (index > 0)
  1297. {
  1298. sbuf.append(' ');
  1299. sbuf.append(data, pos, index);
  1300. pos += index;
  1301. }
  1302. sbuf.append("?>");
  1303. continue;
  1304. case END_DOCUMENT:
  1305. case END_ENTITY:
  1306. continue;
  1307. case BOOL_FALSE:
  1308. case BOOL_TRUE:
  1309. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1310. if (seen) sbuf.append(sep); else seen = true;
  1311. sbuf.append(datum != BOOL_FALSE);
  1312. continue;
  1313. case JOINER:
  1314. continue;
  1315. case CHAR_FOLLOWS:
  1316. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1317. sbuf.append(data, pos, 1 + datum - CHAR_FOLLOWS);
  1318. seen = false;
  1319. pos++;
  1320. continue;
  1321. case POSITION_PAIR_FOLLOWS:
  1322. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1323. if (seen) sbuf.append(sep); else seen = true;
  1324. {
  1325. AbstractSequence seq = (AbstractSequence) objects[getIntN(pos)];
  1326. int ipos = getIntN(pos+2);
  1327. // This could lead to to a lot of copying. FIXME.
  1328. sbuf.append(seq.getIteratorAtPos(ipos));
  1329. pos += 4;
  1330. }
  1331. continue;
  1332. case POSITION_REF_FOLLOWS:
  1333. case OBJECT_REF_FOLLOWS:
  1334. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1335. if (seen) sbuf.append(sep); else seen = true;
  1336. sbuf.append(objects[getIntN(pos)]);
  1337. pos += 2;
  1338. continue;
  1339. case BEGIN_ELEMENT_LONG:
  1340. index = getIntN(pos);
  1341. index += index >= 0 ? pos - 1 : data.length;
  1342. pos += 2;
  1343. index = getIntN(index + 1);
  1344. if (inStartTag) sbuf.append('>');
  1345. else if (seen) sbuf.append(sep);
  1346. sbuf.append('<');
  1347. sbuf.append(objects[index]);
  1348. seen = false;
  1349. inStartTag = true;
  1350. continue;
  1351. case END_ELEMENT_LONG:
  1352. case END_ELEMENT_SHORT:
  1353. if (datum == END_ELEMENT_SHORT)
  1354. {
  1355. index = data[pos++];
  1356. index = data[pos - 2 - index] - BEGIN_ELEMENT_SHORT;
  1357. }
  1358. else
  1359. {
  1360. index = getIntN(pos);
  1361. pos += 6;
  1362. }
  1363. if (inStartTag)
  1364. sbuf.append("/>");
  1365. else
  1366. {
  1367. sbuf.append("</");
  1368. sbuf.append(objects[index]);
  1369. sbuf.append('>');
  1370. }
  1371. inStartTag = false;
  1372. seen = true;
  1373. continue;
  1374. case BEGIN_ATTRIBUTE_LONG:
  1375. index = getIntN(pos);
  1376. sbuf.append(' ');
  1377. sbuf.append(objects[index]);
  1378. sbuf.append("=\"");
  1379. inAttribute = true;
  1380. inStartTag = false;
  1381. pos += 4;
  1382. continue;
  1383. case END_ATTRIBUTE:
  1384. sbuf.append('"');
  1385. inAttribute = false;
  1386. inStartTag = true;
  1387. seen = false;
  1388. continue;
  1389. case INT_FOLLOWS:
  1390. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1391. if (seen) sbuf.append(sep); else seen = true;
  1392. sbuf.append(getIntN(pos));
  1393. pos += 2;
  1394. continue;
  1395. case FLOAT_FOLLOWS:
  1396. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1397. if (seen) sbuf.append(sep); else seen = true;
  1398. sbuf.append(Float.intBitsToFloat(getIntN(pos)));
  1399. pos += 2;
  1400. continue;
  1401. case LONG_FOLLOWS:
  1402. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1403. if (seen) sbuf.append(sep); else seen = true;
  1404. sbuf.append(getLongN(pos));
  1405. pos += 4;
  1406. continue;
  1407. case DOUBLE_FOLLOWS:
  1408. if (inStartTag) { sbuf.append('>'); inStartTag = false; }
  1409. if (seen) sbuf.append(sep); else seen = true;
  1410. sbuf.append(Double.longBitsToDouble(getLongN(pos)));
  1411. pos += 4;
  1412. continue;
  1413. default:
  1414. throw new Error("unknown code:"+(int) datum);
  1415. }
  1416. }
  1417. }
  1418. public boolean hasNext(int ipos)
  1419. {
  1420. int index = posToDataIndex(ipos);
  1421. if (index == data.length)
  1422. return false;
  1423. char ch = data[index];
  1424. return ch != END_ATTRIBUTE && ch != END_ELEMENT_SHORT
  1425. && ch != END_ELEMENT_LONG && ch != END_DOCUMENT;
  1426. }
  1427. public int getNextKind(int ipos)
  1428. {
  1429. return getNextKindI(posToDataIndex(ipos));
  1430. }
  1431. public int getNextKindI (int index)
  1432. {
  1433. if (index == data.length)
  1434. return Sequence.EOF_VALUE;
  1435. char datum = data[index];
  1436. if (datum <= MAX_CHAR_SHORT)
  1437. return Sequence.CHAR_VALUE;
  1438. if (datum >= OBJECT_REF_SHORT
  1439. && datum <= OBJECT_REF_SHORT+OBJECT_REF_SHORT_INDEX_MAX)
  1440. return Sequence.OBJECT_VALUE;
  1441. if (datum >= BEGIN_ELEMENT_SHORT
  1442. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  1443. return Sequence.ELEMENT_VALUE;
  1444. if ((datum & 0xFF00) == BYTE_PREFIX)
  1445. return Sequence.TEXT_BYTE_VALUE;
  1446. if (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
  1447. && datum <= INT_SHORT_ZERO + MAX_INT_SHORT)
  1448. return Sequence.INT_S32_VALUE;
  1449. switch (datum)
  1450. {
  1451. case BOOL_FALSE:
  1452. case BOOL_TRUE:
  1453. return Sequence.BOOLEAN_VALUE;
  1454. case INT_FOLLOWS:
  1455. return Sequence.INT_S32_VALUE;
  1456. case LONG_FOLLOWS:
  1457. return Sequence.INT_S64_VALUE;
  1458. case FLOAT_FOLLOWS:
  1459. return Sequence.FLOAT_VALUE;
  1460. case DOUBLE_FOLLOWS:
  1461. return Sequence.DOUBLE_VALUE;
  1462. case CHAR_FOLLOWS:
  1463. return Sequence.CHAR_VALUE;
  1464. case BEGIN_DOCUMENT:
  1465. return Sequence.DOCUMENT_VALUE;
  1466. case BEGIN_ENTITY:
  1467. return getNextKind((index+BEGIN_ENTITY_SIZE) << 1);
  1468. case BEGIN_ELEMENT_LONG:
  1469. return Sequence.ELEMENT_VALUE;
  1470. case END_ELEMENT_SHORT:
  1471. case END_ELEMENT_LONG:
  1472. case END_ATTRIBUTE:
  1473. case END_DOCUMENT:
  1474. case END_ENTITY:
  1475. return Sequence.EOF_VALUE;
  1476. case BEGIN_ATTRIBUTE_LONG:
  1477. return Sequence.ATTRIBUTE_VALUE;
  1478. case CDATA_SECTION:
  1479. return Sequence.CDATA_VALUE;
  1480. case COMMENT:
  1481. return Sequence.COMMENT_VALUE;
  1482. case PROCESSING_INSTRUCTION:
  1483. return Sequence.PROCESSING_INSTRUCTION_VALUE;
  1484. case DOCUMENT_URI: // FIXME
  1485. case POSITION_REF_FOLLOWS: // FIXME
  1486. case POSITION_PAIR_FOLLOWS:
  1487. case OBJECT_REF_FOLLOWS:
  1488. case JOINER: // FIXME
  1489. default:
  1490. return Sequence.OBJECT_VALUE;
  1491. }
  1492. }
  1493. public Object getNextTypeObject (int ipos)
  1494. {
  1495. int index = posToDataIndex(ipos);
  1496. char datum;
  1497. for (;;)
  1498. {
  1499. if (index == data.length)
  1500. return null;
  1501. datum = data[index];
  1502. if (datum != BEGIN_ENTITY)
  1503. break;
  1504. index += BEGIN_ENTITY_SIZE;
  1505. }
  1506. if (datum >= BEGIN_ELEMENT_SHORT
  1507. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  1508. index = datum-BEGIN_ELEMENT_SHORT;
  1509. else if (datum == BEGIN_ELEMENT_LONG)
  1510. {
  1511. int j = getIntN(index+1);
  1512. j += j < 0 ? data.length : index;
  1513. index = getIntN(j + 1);
  1514. }
  1515. else if (datum == BEGIN_ATTRIBUTE_LONG)
  1516. index = getIntN(index + 1);
  1517. else if (datum == PROCESSING_INSTRUCTION)
  1518. index = getIntN(index + 1);
  1519. else
  1520. return null;
  1521. return index < 0 ? null : objects[index];
  1522. }
  1523. public Object getPosPrevious(int ipos)
  1524. {
  1525. if ((ipos & 1) != 0 && ipos != -1)
  1526. return getPosNext(ipos - 3);
  1527. else
  1528. return super.getPosPrevious(ipos);
  1529. }
  1530. private Object copyToList(int startPosition, int endPosition)
  1531. {
  1532. return new TreeList(this, startPosition, endPosition);
  1533. }
  1534. /** Return following value (like getPosNext), as an integer. */
  1535. public int getPosNextInt (int ipos)
  1536. {
  1537. int index = posToDataIndex(ipos);
  1538. if (index < data.length)
  1539. {
  1540. char datum = data[index];
  1541. if (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
  1542. && datum <= INT_SHORT_ZERO + MAX_INT_SHORT)
  1543. return datum-INT_SHORT_ZERO;
  1544. if (datum == INT_FOLLOWS)
  1545. return getIntN(index+1);
  1546. }
  1547. return ((Number) getPosNext(ipos)).intValue();
  1548. }
  1549. public Object getPosNext(int ipos)
  1550. {
  1551. int index = posToDataIndex(ipos);
  1552. if (index == data.length)
  1553. return Sequence.eofValue;
  1554. char datum = data[index];
  1555. if (datum <= MAX_CHAR_SHORT)
  1556. return Convert.toObject(datum);
  1557. if (datum >= OBJECT_REF_SHORT
  1558. && datum <= OBJECT_REF_SHORT+OBJECT_REF_SHORT_INDEX_MAX)
  1559. return objects[datum-OBJECT_REF_SHORT];
  1560. if (datum >= BEGIN_ELEMENT_SHORT
  1561. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  1562. return copyToList(index, index + data[index+1] + 2);
  1563. /*
  1564. if ((datum & 0xFF00) == BYTE_PREFIX)
  1565. return Sequence.TEXT_BYTE_VALUE;
  1566. */
  1567. if (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
  1568. && datum <= INT_SHORT_ZERO + MAX_INT_SHORT)
  1569. return Convert.toObject(datum-INT_SHORT_ZERO);
  1570. switch (datum)
  1571. {
  1572. case BEGIN_DOCUMENT:
  1573. {
  1574. int end_offset = getIntN(index+1);
  1575. end_offset += end_offset < 0 ? data.length : index;
  1576. end_offset++;
  1577. /* Need to be careful about this.
  1578. if (index == 0
  1579. && (end_offset == data.length
  1580. || (end_offset == gapStart && gapEnd == data.length)))
  1581. return this;
  1582. */
  1583. return copyToList(index, end_offset);
  1584. }
  1585. case BOOL_FALSE:
  1586. case BOOL_TRUE:
  1587. return Convert.toObject(datum != BOOL_FALSE);
  1588. case INT_FOLLOWS:
  1589. return Convert.toObject(getIntN(index+1));
  1590. case LONG_FOLLOWS:
  1591. return Convert.toObject(getLongN(index+1));
  1592. case FLOAT_FOLLOWS:
  1593. return Convert.toObject(Float.intBitsToFloat(getIntN(index+1)));
  1594. case DOUBLE_FOLLOWS:
  1595. return Convert.toObject(Double.longBitsToDouble(getLongN(index+1)));
  1596. case CHAR_FOLLOWS:
  1597. return Convert.toObject(data[index+1]);
  1598. case BEGIN_ATTRIBUTE_LONG:
  1599. {
  1600. int end_offset = getIntN(index+3);
  1601. end_offset += end_offset < 0 ? data.length : index;
  1602. return copyToList(index, end_offset+1);
  1603. }
  1604. case BEGIN_ELEMENT_LONG:
  1605. {
  1606. int end_offset = getIntN(index+1);
  1607. end_offset += end_offset < 0 ? data.length : index;
  1608. return copyToList(index, end_offset+7);
  1609. }
  1610. case END_ELEMENT_SHORT:
  1611. case END_ELEMENT_LONG:
  1612. case END_ATTRIBUTE:
  1613. case END_DOCUMENT:
  1614. return Sequence.eofValue;
  1615. case POSITION_REF_FOLLOWS:
  1616. case OBJECT_REF_FOLLOWS:
  1617. return objects[getIntN(index+1)];
  1618. case JOINER:
  1619. return "";
  1620. case POSITION_PAIR_FOLLOWS: //FIXME
  1621. AbstractSequence seq = (AbstractSequence) objects[getIntN(index+1)];
  1622. ipos = getIntN(index+3);
  1623. return seq.getIteratorAtPos(ipos);
  1624. default:
  1625. throw unsupported("getPosNext, code="+Integer.toHexString(datum));
  1626. }
  1627. }
  1628. public void stringValue (int startIndex, int endIndex, StringBuffer sbuf)
  1629. {
  1630. int index = startIndex;
  1631. while (index < endIndex && index >= 0)
  1632. index = stringValue(false, index, sbuf);
  1633. }
  1634. public int stringValue(int index, StringBuffer sbuf)
  1635. {
  1636. int next = nextNodeIndex(index, -1 >>> 1);
  1637. if (next > index)
  1638. {
  1639. stringValue(index, next, sbuf);
  1640. return index;
  1641. }
  1642. else
  1643. return stringValue(false, index, sbuf);
  1644. }
  1645. public int stringValue(boolean inElement, int index, StringBuffer sbuf)
  1646. {
  1647. Object value = null;
  1648. int doChildren = 0, j;
  1649. if (index >= gapStart)
  1650. index += gapEnd - gapStart;
  1651. if (index == data.length)
  1652. return -1;
  1653. char datum = data[index];
  1654. index++;
  1655. boolean spaceNeeded = false;
  1656. if (datum <= MAX_CHAR_SHORT)
  1657. {
  1658. sbuf.append(datum);
  1659. return index;
  1660. }
  1661. if (datum >= OBJECT_REF_SHORT
  1662. && datum <= OBJECT_REF_SHORT+OBJECT_REF_SHORT_INDEX_MAX)
  1663. {
  1664. if (spaceNeeded)
  1665. sbuf.append(' ');
  1666. value = objects[datum-OBJECT_REF_SHORT];
  1667. spaceNeeded = false;
  1668. }
  1669. else if (datum >= BEGIN_ELEMENT_SHORT
  1670. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  1671. {
  1672. doChildren = index + 2;
  1673. index = data[index] + index + 1;
  1674. }
  1675. else if ((datum & 0xFF00) == BYTE_PREFIX)
  1676. {
  1677. sbuf.append(datum & 0xFF);
  1678. return index;
  1679. }
  1680. else if (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
  1681. && datum <= INT_SHORT_ZERO + MAX_INT_SHORT)
  1682. {
  1683. sbuf.append((int) datum - INT_SHORT_ZERO);
  1684. return index;
  1685. }
  1686. else
  1687. {
  1688. switch (datum)
  1689. {
  1690. case DOCUMENT_URI:
  1691. return index + 2;
  1692. case PROCESSING_INSTRUCTION:
  1693. index += 2;
  1694. /* ... fall through ... */
  1695. case CDATA_SECTION:
  1696. case COMMENT:
  1697. {
  1698. int length = getIntN(index);
  1699. index += 2;
  1700. if (! inElement || datum == CDATA_SECTION)
  1701. sbuf.append(data, index, length);
  1702. return index + length;
  1703. }
  1704. case BOOL_FALSE:
  1705. case BOOL_TRUE:
  1706. if (spaceNeeded)
  1707. sbuf.append(' ');
  1708. sbuf.append(datum != BOOL_FALSE);
  1709. spaceNeeded = true;
  1710. return index;
  1711. case INT_FOLLOWS:
  1712. if (spaceNeeded)
  1713. sbuf.append(' ');
  1714. sbuf.append(getIntN(index));
  1715. spaceNeeded = true;
  1716. return index + 2;
  1717. case LONG_FOLLOWS:
  1718. if (spaceNeeded)
  1719. sbuf.append(' ');
  1720. sbuf.append(getLongN(index));
  1721. spaceNeeded = true;
  1722. return index + 4;
  1723. case FLOAT_FOLLOWS:
  1724. if (spaceNeeded)
  1725. sbuf.append(' ');
  1726. sbuf.append(Float.intBitsToFloat(getIntN(index)));
  1727. spaceNeeded = true;
  1728. return index + 2;
  1729. case DOUBLE_FOLLOWS:
  1730. if (spaceNeeded)
  1731. sbuf.append(' ');
  1732. sbuf.append(Double.longBitsToDouble(getLongN(index)));
  1733. spaceNeeded = true;
  1734. return index + 4;
  1735. case CHAR_FOLLOWS:
  1736. spaceNeeded = false;
  1737. sbuf.append(data[index]);
  1738. return index + 1;
  1739. case BEGIN_DOCUMENT:
  1740. case BEGIN_ENTITY:
  1741. doChildren = index + 4;
  1742. index = nextDataIndex(index-1);
  1743. break;
  1744. case BEGIN_ELEMENT_LONG:
  1745. spaceNeeded = false;
  1746. doChildren = index + 2;
  1747. j = getIntN(index);
  1748. j += j < 0 ? data.length : index-1;
  1749. index = j + 7;
  1750. break;
  1751. case JOINER:
  1752. spaceNeeded = false;
  1753. break;
  1754. case END_ELEMENT_SHORT:
  1755. case END_ELEMENT_LONG:
  1756. case END_ATTRIBUTE:
  1757. case END_DOCUMENT:
  1758. case END_ENTITY:
  1759. return -1;
  1760. case BEGIN_ATTRIBUTE_LONG:
  1761. if (! inElement)
  1762. doChildren = index + 4;
  1763. int end = getIntN(index+2);
  1764. index = end + (end < 0 ? data.length + 1: index);
  1765. break;
  1766. case POSITION_PAIR_FOLLOWS:
  1767. {
  1768. AbstractSequence seq = (AbstractSequence) objects[getIntN(index)];
  1769. int ipos = getIntN(index+2);
  1770. ((TreeList) seq).stringValue(inElement, ipos >> 1, sbuf);
  1771. index += 4;
  1772. }
  1773. break;
  1774. case POSITION_REF_FOLLOWS:
  1775. case OBJECT_REF_FOLLOWS:
  1776. default:
  1777. throw new Error("unimplemented: "+Integer.toHexString(datum)+" at:"+index);
  1778. }
  1779. }
  1780. if (value != null)
  1781. sbuf.append(value);
  1782. if (doChildren > 0)
  1783. {
  1784. do
  1785. {
  1786. doChildren = stringValue(true, doChildren, sbuf);
  1787. }
  1788. while (doChildren >= 0);
  1789. }
  1790. return index;
  1791. }
  1792. public int createRelativePos(int istart, int offset, boolean isAfter)
  1793. {
  1794. if (isAfter)
  1795. {
  1796. if (offset == 0)
  1797. {
  1798. if ((istart & 1) != 0)
  1799. return istart;
  1800. if (istart == 0)
  1801. return 1;
  1802. }
  1803. offset--;
  1804. }
  1805. if (offset < 0)
  1806. throw unsupported("backwards createRelativePos");
  1807. int pos = posToDataIndex(istart);
  1808. while (--offset >= 0)
  1809. {
  1810. pos = nextDataIndex(pos);
  1811. if (pos < 0)
  1812. throw new IndexOutOfBoundsException();
  1813. }
  1814. if (pos >= gapEnd)
  1815. pos -= gapEnd - gapStart;
  1816. return isAfter ? ((pos + 1) << 1) | 1 : (pos << 1);
  1817. }
  1818. /** Skip all primitive content nodes. */
  1819. public final int nextNodeIndex (int pos, int limit)
  1820. {
  1821. if ((limit | 0x80000000) == -1) // kludge
  1822. limit = data.length;
  1823. for (;;)
  1824. {
  1825. if (pos == gapStart)
  1826. pos = gapEnd;
  1827. if (pos >= limit)
  1828. return pos;
  1829. char datum = data[pos];
  1830. if (datum <= MAX_CHAR_SHORT
  1831. || (datum >= OBJECT_REF_SHORT
  1832. && datum <= OBJECT_REF_SHORT+OBJECT_REF_SHORT_INDEX_MAX)
  1833. || (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
  1834. && datum <= INT_SHORT_ZERO + MAX_INT_SHORT)
  1835. || (datum & 0xFF00) == BYTE_PREFIX)
  1836. {
  1837. pos++;
  1838. continue;
  1839. }
  1840. if (datum >= BEGIN_ELEMENT_SHORT
  1841. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  1842. return pos;
  1843. switch (datum)
  1844. {
  1845. case DOCUMENT_URI:
  1846. pos += 3;
  1847. break;
  1848. case JOINER:
  1849. pos += 1;
  1850. break;
  1851. case PROCESSING_INSTRUCTION:
  1852. case COMMENT:
  1853. case BEGIN_DOCUMENT:
  1854. case BEGIN_ELEMENT_LONG:
  1855. case BEGIN_ATTRIBUTE_LONG:
  1856. return pos;
  1857. case BEGIN_ENTITY:
  1858. pos += 5;
  1859. break;
  1860. case END_ELEMENT_SHORT:
  1861. case END_ELEMENT_LONG:
  1862. case END_ATTRIBUTE:
  1863. case END_DOCUMENT:
  1864. case END_ENTITY:
  1865. return pos;
  1866. case CDATA_SECTION:
  1867. default:
  1868. pos = nextDataIndex(pos);
  1869. continue;
  1870. }
  1871. }
  1872. }
  1873. public int nextMatching(int startPos, ItemPredicate predicate,
  1874. int endPos, boolean descend)
  1875. {
  1876. int start = posToDataIndex(startPos);
  1877. int limit = posToDataIndex(endPos);
  1878. int pos = start;
  1879. if (predicate instanceof NodePredicate)
  1880. pos = nextNodeIndex(pos, limit);
  1881. boolean checkAttribute = false; // true if attribute nodes could match.
  1882. boolean checkNode;
  1883. boolean checkText;
  1884. boolean checkElement; // true if element nodes could match.
  1885. if (predicate instanceof ElementPredicate)
  1886. {
  1887. checkNode = true;
  1888. checkElement = true;
  1889. checkText = false;
  1890. }
  1891. else if (predicate instanceof AttributePredicate)
  1892. {
  1893. checkNode = true;
  1894. checkElement = false;
  1895. checkText = false;
  1896. }
  1897. else
  1898. {
  1899. checkNode = true;
  1900. checkElement = true;
  1901. checkText = true;
  1902. }
  1903. int next;
  1904. for (;; pos = next)
  1905. {
  1906. if (pos == gapStart)
  1907. pos = gapEnd;
  1908. if (pos >= limit && limit != -1)
  1909. return 0;
  1910. int j;
  1911. char datum = data[pos];
  1912. if (datum <= MAX_CHAR_SHORT
  1913. || (datum >= OBJECT_REF_SHORT
  1914. && datum <= OBJECT_REF_SHORT+OBJECT_REF_SHORT_INDEX_MAX)
  1915. || (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
  1916. && datum <= INT_SHORT_ZERO + MAX_INT_SHORT))
  1917. {
  1918. if (checkText && predicate.isInstancePos(this, pos << 1))
  1919. {
  1920. if (pos >= gapEnd)
  1921. pos -= gapEnd - gapStart;
  1922. return pos << 1;
  1923. }
  1924. next = pos + 1;
  1925. continue;
  1926. }
  1927. switch (datum)
  1928. {
  1929. case DOCUMENT_URI:
  1930. next = pos + 3;
  1931. continue;
  1932. case BEGIN_DOCUMENT:
  1933. next = pos + 5;
  1934. if (checkNode) break;
  1935. continue;
  1936. case BEGIN_ENTITY:
  1937. next = pos + 5;
  1938. continue;
  1939. case POSITION_REF_FOLLOWS:
  1940. case OBJECT_REF_FOLLOWS:
  1941. case INT_FOLLOWS:
  1942. case FLOAT_FOLLOWS:
  1943. next = pos + 3;
  1944. if (checkText) break;
  1945. continue;
  1946. case CHAR_FOLLOWS:
  1947. next = pos + 2;
  1948. continue;
  1949. case END_ELEMENT_SHORT:
  1950. if (! descend)
  1951. return 0;
  1952. next = pos + 2;
  1953. continue;
  1954. case POSITION_PAIR_FOLLOWS:
  1955. next = pos + 5;
  1956. if (checkText) break;
  1957. continue;
  1958. case END_ELEMENT_LONG:
  1959. if (! descend)
  1960. return 0;
  1961. next = pos + 7;
  1962. continue;
  1963. case END_ATTRIBUTE:
  1964. case END_DOCUMENT:
  1965. if (! descend)
  1966. return 0;
  1967. /* ... fall through ...*/
  1968. case END_ENTITY:
  1969. next = pos + 1;
  1970. continue;
  1971. case BEGIN_ATTRIBUTE_LONG:
  1972. if (checkNode)
  1973. {
  1974. j = getIntN(pos+3);
  1975. next = j + 1 + (j < 0 ? data.length : pos);
  1976. }
  1977. else
  1978. next = pos + 5;
  1979. if (checkAttribute) break;
  1980. continue;
  1981. case BOOL_FALSE:
  1982. case BOOL_TRUE:
  1983. next = pos + 1;
  1984. if (checkText) break;
  1985. continue;
  1986. case JOINER:
  1987. next = pos + 1;
  1988. continue;
  1989. case LONG_FOLLOWS:
  1990. case DOUBLE_FOLLOWS:
  1991. next = pos + 5;
  1992. if (checkText) break;
  1993. continue;
  1994. case PROCESSING_INSTRUCTION:
  1995. next = pos + 5 + getIntN(pos+3);
  1996. if (checkNode) break;
  1997. continue;
  1998. case COMMENT:
  1999. next = pos + 3 + getIntN(pos+1);
  2000. if (checkNode) break;
  2001. continue;
  2002. case CDATA_SECTION:
  2003. next = pos + 3 + getIntN(pos+1);
  2004. if (checkText) break;
  2005. continue;
  2006. case BEGIN_ELEMENT_LONG:
  2007. if (descend)
  2008. next = pos + 3;
  2009. else
  2010. {
  2011. j = getIntN(pos+1);
  2012. next = j + (j < 0 ? data.length : pos) + 7;
  2013. }
  2014. if (checkElement) break;
  2015. continue;
  2016. default:
  2017. if (datum >= BEGIN_ELEMENT_SHORT
  2018. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  2019. {
  2020. if (descend)
  2021. next = pos + 3;
  2022. else
  2023. next = pos + data[pos+1] + 2;
  2024. if (checkElement) break;
  2025. }
  2026. else
  2027. throw new Error("unknown code:"+(int) datum);
  2028. continue;
  2029. }
  2030. if (pos > start && predicate.isInstancePos(this, pos << 1))
  2031. {
  2032. if (pos >= gapEnd)
  2033. pos -= gapEnd - gapStart;
  2034. return pos << 1;
  2035. }
  2036. }
  2037. }
  2038. public int nextPos (int position)
  2039. {
  2040. int index = posToDataIndex(position);
  2041. if (index == data.length)
  2042. return 0;
  2043. if (index >= gapEnd)
  2044. index -= gapEnd - gapStart;
  2045. return (index << 1) + 3;
  2046. }
  2047. public final int nextDataIndex(int pos)
  2048. {
  2049. if (pos == gapStart)
  2050. pos = gapEnd;
  2051. if (pos == data.length)
  2052. return -1;
  2053. int j;
  2054. char datum = data[pos++];
  2055. if (datum <= MAX_CHAR_SHORT
  2056. || (datum >= OBJECT_REF_SHORT
  2057. && datum <= OBJECT_REF_SHORT+OBJECT_REF_SHORT_INDEX_MAX)
  2058. || (datum >= INT_SHORT_ZERO + MIN_INT_SHORT
  2059. && datum <= INT_SHORT_ZERO + MAX_INT_SHORT))
  2060. return pos;
  2061. if (datum >= BEGIN_ELEMENT_SHORT
  2062. && datum <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  2063. return data[pos] + pos + 1;
  2064. switch (datum)
  2065. {
  2066. case BEGIN_DOCUMENT:
  2067. j = getIntN(pos);
  2068. j += j < 0 ? data.length : pos-1;
  2069. return j + 1;
  2070. case BEGIN_ENTITY:
  2071. j = pos + (BEGIN_ENTITY_SIZE-1);
  2072. for (;;)
  2073. {
  2074. if (j == gapStart)
  2075. j = gapEnd;
  2076. if (j == data.length)
  2077. return -1; // actually error.
  2078. if (data[j] == END_ENTITY)
  2079. return j + 1;
  2080. j = nextDataIndex(j);
  2081. }
  2082. case BOOL_FALSE:
  2083. case BOOL_TRUE:
  2084. case JOINER:
  2085. return pos;
  2086. case CHAR_FOLLOWS:
  2087. return pos + 1;
  2088. case POSITION_REF_FOLLOWS:
  2089. case OBJECT_REF_FOLLOWS:
  2090. case INT_FOLLOWS:
  2091. case FLOAT_FOLLOWS:
  2092. return pos + 2;
  2093. case POSITION_PAIR_FOLLOWS:
  2094. return pos + 4;
  2095. case END_ELEMENT_SHORT:
  2096. case END_ELEMENT_LONG:
  2097. case END_ATTRIBUTE:
  2098. case END_DOCUMENT:
  2099. case END_ENTITY:
  2100. return -1;
  2101. case BEGIN_ELEMENT_LONG:
  2102. j = getIntN(pos);
  2103. j += j < 0 ? data.length : pos-1;
  2104. return j + 7;
  2105. case BEGIN_ATTRIBUTE_LONG:
  2106. j = getIntN(pos+2);
  2107. j += j < 0 ? data.length : pos-1;
  2108. return j + 1;
  2109. case LONG_FOLLOWS:
  2110. case DOUBLE_FOLLOWS:
  2111. return pos + 4;
  2112. case PROCESSING_INSTRUCTION:
  2113. pos += 2;
  2114. // ... fall through ...
  2115. case CDATA_SECTION:
  2116. case COMMENT:
  2117. return pos + 2 + getIntN(pos);
  2118. default:
  2119. throw new Error("unknown code:"+Integer.toHexString((int) datum));
  2120. }
  2121. }
  2122. public Object documentUriOfPos (int pos)
  2123. {
  2124. int index = posToDataIndex(pos);
  2125. if (index == data.length)
  2126. return null;
  2127. if (data[index] == BEGIN_DOCUMENT)
  2128. {
  2129. int next = index + 5;
  2130. if (next == gapStart)
  2131. next = gapEnd;
  2132. if (next < data.length && data[next] == DOCUMENT_URI)
  2133. return objects[getIntN(next+1)];
  2134. }
  2135. return null;
  2136. }
  2137. /** Compare two positions, and indicate their relative order. */
  2138. public int compare(int ipos1, int ipos2)
  2139. {
  2140. // It's difficult to optimize this, because because if (say) isAfter(ipos1)
  2141. // then we need nextDataIndex((ipos1>>>1)-1). In that case comparing
  2142. // (ipos1>>>1)-1 and (pos2>>>1)-1 tells us nothing, since the former
  2143. // could be a BEGIN_ELEMENT, while the latter might be a node inside
  2144. // the element.
  2145. int i1 = posToDataIndex(ipos1);
  2146. int i2 = posToDataIndex(ipos2);
  2147. return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
  2148. }
  2149. protected int getIndexDifference(int ipos1, int ipos0)
  2150. {
  2151. int i0 = posToDataIndex(ipos0);
  2152. int i1 = posToDataIndex(ipos1);
  2153. boolean negate = false;
  2154. if (i0 > i1)
  2155. {
  2156. negate = true;
  2157. int i = i1; i1 = i0; i0 = i;
  2158. }
  2159. int i = 0;
  2160. while (i0 < i1)
  2161. {
  2162. i0 = nextDataIndex(i0);
  2163. i++;
  2164. }
  2165. return negate ? -i : i;
  2166. }
  2167. public int nextIndex(int ipos)
  2168. {
  2169. return getIndexDifference(ipos, startPos());
  2170. }
  2171. public int hashCode()
  2172. {
  2173. // Calculating a real hashCode is real pain.
  2174. return System.identityHashCode(this);
  2175. }
  2176. public void consume(Consumer out)
  2177. {
  2178. consumeIRange(0, data.length, out);
  2179. }
  2180. public void statistics ()
  2181. {
  2182. java.io.PrintWriter out = new java.io.PrintWriter(System.out);
  2183. statistics(out);
  2184. out.flush();
  2185. }
  2186. public void statistics (java.io.PrintWriter out)
  2187. {
  2188. out.print("data array length: "); out.println(data.length);
  2189. out.print("data array gap: "); out.println(gapEnd-gapStart);
  2190. out.print("object array length: "); out.println(objects.length);
  2191. }
  2192. // /* DEBUGGING
  2193. public void dump ()
  2194. {
  2195. java.io.PrintWriter out = new java.io.PrintWriter(System.out);
  2196. dump(out);
  2197. out.flush();
  2198. }
  2199. public void dump (java.io.PrintWriter out)
  2200. {
  2201. out.println(getClass().getName()+" @"+Integer.toHexString(System.identityHashCode(this))
  2202. + " gapStart:"+gapStart+" gapEnd:"+gapEnd+" length:"+data.length);
  2203. dump(out, 0, data.length);
  2204. }
  2205. public void dump (java.io.PrintWriter out, int start, int limit)
  2206. {
  2207. int toskip = 0;
  2208. // Skip follow-on words.
  2209. boolean skipFollowingWords = true;
  2210. for (int i = start; i < limit; i++)
  2211. {
  2212. if (i < gapStart || i >= gapEnd)
  2213. {
  2214. int j; long l;
  2215. int ch = data[i];
  2216. out.print(""+i+": 0x"+Integer.toHexString(ch)+'='+((short) ch));
  2217. if (--toskip < 0)
  2218. {
  2219. if (ch <= MAX_CHAR_SHORT)
  2220. {
  2221. if (ch >= ' ' && ch < 127)
  2222. out.print("='"+((char)ch)+"'");
  2223. else if (ch=='\n')
  2224. out.print("='\\n'");
  2225. else
  2226. out.print("='\\u"+Integer.toHexString(ch)+"'");
  2227. }
  2228. else if (ch >= OBJECT_REF_SHORT
  2229. && ch <= OBJECT_REF_SHORT+OBJECT_REF_SHORT_INDEX_MAX)
  2230. {
  2231. ch = ch - OBJECT_REF_SHORT;
  2232. Object obj = objects[ch];
  2233. out.print("=Object#");
  2234. out.print((int)ch);
  2235. out.print('=');
  2236. out.print(obj);
  2237. if (obj != null) {
  2238. out.print(':');
  2239. out.print(obj.getClass().getName());
  2240. }
  2241. out.print('@');
  2242. out.print(Integer.toHexString(System.identityHashCode(obj)));
  2243. }
  2244. else if (ch >= BEGIN_ELEMENT_SHORT
  2245. && ch <= BEGIN_ELEMENT_SHORT+BEGIN_ELEMENT_SHORT_INDEX_MAX)
  2246. {
  2247. ch = ch - BEGIN_ELEMENT_SHORT;
  2248. j = data[i+1] + i;
  2249. out.print("=BEGIN_ELEMENT_SHORT end:"+j+" index#"+((int)ch)+"=<"+objects[ch]+'>');
  2250. toskip = 2;
  2251. }
  2252. else if (ch >= INT_SHORT_ZERO + MIN_INT_SHORT
  2253. && ch <= INT_SHORT_ZERO + MAX_INT_SHORT)
  2254. {
  2255. out.print("= INT_SHORT:"+(ch-INT_SHORT_ZERO));
  2256. }
  2257. else
  2258. {
  2259. switch (ch)
  2260. {
  2261. case INT_FOLLOWS:
  2262. j = getIntN(i+1);
  2263. out.print("=INT_FOLLOWS value:"+j);
  2264. toskip = 2;
  2265. break;
  2266. case LONG_FOLLOWS:
  2267. l = getLongN(i+1);
  2268. out.print("=LONG_FOLLOWS value:"+l);
  2269. toskip = 4;
  2270. break;
  2271. case FLOAT_FOLLOWS:
  2272. j = getIntN(i+1);
  2273. out.write("=FLOAT_FOLLOWS value:"
  2274. +Float.intBitsToFloat(j));
  2275. toskip = 2;
  2276. break;
  2277. case DOUBLE_FOLLOWS:
  2278. l = getLongN(i+1);
  2279. out.print("=DOUBLE_FOLLOWS value:"
  2280. +Double.longBitsToDouble(l));
  2281. toskip = 4;
  2282. break;
  2283. case BEGIN_DOCUMENT:
  2284. j = getIntN(i+1);
  2285. j += j < 0 ? data.length : i;
  2286. out.print("=BEGIN_DOCUMENT end:");
  2287. out.print(j);
  2288. out.print(" parent:");
  2289. j = getIntN(i+3);
  2290. out.print(j);
  2291. toskip = 4;
  2292. break;
  2293. case BEGIN_ENTITY:
  2294. j = getIntN(i+1);
  2295. out.print("=BEGIN_ENTITY base:");
  2296. out.print(j);
  2297. out.print(" parent:");
  2298. j = getIntN(i+3);
  2299. out.print(j);
  2300. toskip = 4;
  2301. break;
  2302. case END_ENTITY:
  2303. out.print("=END_ENTITY");
  2304. break;
  2305. case DOCUMENT_URI:
  2306. out.print("=DOCUMENT_URI: ");
  2307. j = getIntN(i+1);
  2308. out.print(objects[j]);
  2309. toskip = 2;
  2310. break;
  2311. case COMMENT:
  2312. out.print("=COMMENT: '");
  2313. j = getIntN(i+1);
  2314. out.write(data, i+3, j);
  2315. out.print('\'');
  2316. toskip = 2+j;
  2317. break;
  2318. case CDATA_SECTION:
  2319. out.print("=CDATA: '");
  2320. j = getIntN(i+1);
  2321. out.write(data, i+3, j);
  2322. out.print('\'');
  2323. toskip = 2+j;
  2324. break;
  2325. case PROCESSING_INSTRUCTION:
  2326. out.print("=PROCESSING_INSTRUCTION: ");
  2327. j = getIntN(i+1);
  2328. out.print(objects[j]);
  2329. out.print(" '");
  2330. j = getIntN(i+3);
  2331. out.write(data, i+5, j);
  2332. out.print('\'');
  2333. toskip = 4+j;
  2334. break;
  2335. case END_DOCUMENT:
  2336. out.print("=END_DOCUMENT");
  2337. break;
  2338. case BOOL_FALSE: out.print("= false"); break;
  2339. case BOOL_TRUE: out.print("= true"); break;
  2340. case JOINER: out.print("= joiner"); break;
  2341. case CHAR_FOLLOWS:
  2342. out.print("=CHAR_FOLLOWS"); toskip = 1; break;
  2343. case POSITION_REF_FOLLOWS:
  2344. case OBJECT_REF_FOLLOWS:
  2345. toskip = 2; break;
  2346. case END_ELEMENT_SHORT:
  2347. out.print("=END_ELEMENT_SHORT begin:");
  2348. j = i - data[i+1];
  2349. out.print(j);
  2350. j = data[j] - BEGIN_ELEMENT_SHORT;
  2351. out.print(" -> #");
  2352. out.print(j);
  2353. out.print("=<");
  2354. out.print(objects[j]);
  2355. out.print('>');
  2356. toskip = 1; break;
  2357. case BEGIN_ELEMENT_LONG:
  2358. j = getIntN(i+1);
  2359. j += j < 0 ? data.length : i;
  2360. out.print("=BEGIN_ELEMENT_LONG end:");
  2361. out.print(j);
  2362. j = getIntN(j + 1);
  2363. out.print(" -> #");
  2364. out.print(j);
  2365. if (j >= 0 && j+1 < objects.length)
  2366. out.print("=<"+objects[j]+'>');
  2367. else
  2368. out.print("=<out-of-bounds>");
  2369. toskip = 2;
  2370. break;
  2371. case END_ELEMENT_LONG:
  2372. j = getIntN(i+1);
  2373. out.print("=END_ELEMENT_LONG name:"+j
  2374. +"=<"+objects[j]+'>');
  2375. j = getIntN(i+3);
  2376. j = j < 0 ? i + j : j;
  2377. out.print(" begin:"+j);
  2378. j = getIntN(i+5);
  2379. j = j < 0 ? i + j : j;
  2380. out.print(" parent:"+j);
  2381. toskip = 6;
  2382. break;
  2383. case BEGIN_ATTRIBUTE_LONG:
  2384. j = getIntN(i+1);
  2385. out.print("=BEGIN_ATTRIBUTE name:"+j
  2386. +"="+objects[j]);
  2387. j = getIntN(i+3);
  2388. j += j < 0 ? data.length : i;
  2389. out.print(" end:"+j);
  2390. toskip = 4;
  2391. break;
  2392. case END_ATTRIBUTE: out.print("=END_ATTRIBUTE"); break;
  2393. case POSITION_PAIR_FOLLOWS:
  2394. out.print("=POSITION_PAIR_FOLLOWS seq:");
  2395. {
  2396. j = getIntN(i+1); out.print(j);
  2397. out.print('=');
  2398. Object seq = objects[j];
  2399. out.print(seq==null?null:seq.getClass().getName());
  2400. out.print('@');
  2401. if (seq == null) out.print("null");
  2402. else out.print(Integer.toHexString(System.identityHashCode(seq)));
  2403. out.print(" ipos:");
  2404. out.print(getIntN(i+3));
  2405. }
  2406. toskip = 4;
  2407. /*
  2408. AbstractSequence seq = (AbstractSequence) objects[getIntN(i+1)];
  2409. ipos = getIntN(i+3);
  2410. */
  2411. break;
  2412. }
  2413. }
  2414. }
  2415. out.println();
  2416. if (skipFollowingWords && toskip > 0)
  2417. {
  2418. i += toskip;
  2419. toskip = 0;
  2420. }
  2421. }
  2422. }
  2423. }
  2424. // DEBUGGING */
  2425. }