XmlBinaryDictionaryReader.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197
  1. //
  2. // XmlBinaryDictionaryReader.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  6. //
  7. // Copyright (C) 2005, 2007 Novell, Inc. http://www.novell.com
  8. //
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. using System;
  30. using System.Collections;
  31. using System.Collections.Specialized;
  32. using System.Collections.Generic;
  33. using System.Globalization;
  34. using System.IO;
  35. using System.Text;
  36. using QName = System.Xml.XmlQualifiedName;
  37. using BF = System.Xml.XmlBinaryFormat;
  38. namespace System.Xml
  39. {
  40. // FIXME:
  41. // - support XmlDictionaryReaderQuotas.
  42. internal class XmlBinaryDictionaryReader : XmlDictionaryReader, IXmlNamespaceResolver
  43. {
  44. internal interface ISource
  45. {
  46. int Position { get; }
  47. int ReadByte ();
  48. int Read (byte [] data, int offset, int count);
  49. BinaryReader Reader { get; }
  50. }
  51. internal class StreamSource : ISource
  52. {
  53. BinaryReader reader;
  54. public StreamSource (Stream stream)
  55. {
  56. this.reader = new BinaryReader (stream);
  57. }
  58. public int Position {
  59. get { return (int) reader.BaseStream.Position; }
  60. }
  61. public BinaryReader Reader {
  62. get { return reader; }
  63. }
  64. public int ReadByte ()
  65. {
  66. return reader.BaseStream.ReadByte ();
  67. }
  68. public int Read (byte [] data, int offset, int count)
  69. {
  70. return reader.BaseStream.Read (data, offset, count);
  71. }
  72. }
  73. class NodeInfo
  74. {
  75. public NodeInfo ()
  76. {
  77. }
  78. public NodeInfo (bool isAttr)
  79. {
  80. IsAttributeValue = isAttr;
  81. }
  82. public bool IsAttributeValue;
  83. public int Position;
  84. public string Prefix;
  85. public XmlDictionaryString DictLocalName;
  86. public XmlDictionaryString DictNS;
  87. public XmlDictionaryString DictValue; // BF.TextIndex
  88. public XmlNodeType NodeType;
  89. public object TypedValue;
  90. public byte ValueType;
  91. // -1 for nothing,
  92. // -2 for that of element (only for attribute),
  93. // 0 or more to fill later
  94. public int NSSlot;
  95. string name = String.Empty;
  96. string local_name = String.Empty;
  97. string ns = String.Empty;
  98. string value;
  99. public string LocalName {
  100. get { return DictLocalName != null ? DictLocalName.Value : local_name; }
  101. set {
  102. DictLocalName = null;
  103. local_name = value;
  104. }
  105. }
  106. public string NS {
  107. get { return DictNS != null ? DictNS.Value : ns; }
  108. set {
  109. DictNS = null;
  110. ns = value;
  111. }
  112. }
  113. public string Name {
  114. get {
  115. if (name.Length == 0)
  116. name = Prefix.Length > 0 ?
  117. String.Concat (Prefix, ":", LocalName) :
  118. LocalName;
  119. return name;
  120. }
  121. }
  122. public virtual string Value {
  123. get {
  124. switch (ValueType) {
  125. case 0:
  126. case BF.Comment:
  127. case BF.Chars8:
  128. case BF.Chars16:
  129. case BF.Chars32:
  130. case BF.EmptyText:
  131. case BF.Utf16_8:
  132. case BF.Utf16_16:
  133. case BF.Utf16_32:
  134. return value;
  135. case BF.TextIndex:
  136. return DictValue.Value;
  137. case BF.Zero:
  138. return "0";
  139. case BF.One:
  140. return "1";
  141. case BF.BoolTrue:
  142. return "true";
  143. case BF.BoolFalse:
  144. return "false";
  145. case BF.Int8:
  146. return XmlConvert.ToString ((byte) TypedValue);
  147. case BF.Int16:
  148. return XmlConvert.ToString ((short) TypedValue);
  149. case BF.Int32:
  150. return XmlConvert.ToString ((int) TypedValue);
  151. case BF.Int64:
  152. return XmlConvert.ToString ((long) TypedValue);
  153. case BF.Single:
  154. return XmlConvert.ToString ((float) TypedValue);
  155. case BF.Double:
  156. return XmlConvert.ToString ((double) TypedValue);
  157. case BF.Decimal:
  158. return XmlConvert.ToString ((decimal) TypedValue);
  159. case BF.DateTime:
  160. return XmlConvert.ToString ((DateTime) TypedValue, XmlDateTimeSerializationMode.RoundtripKind);
  161. case BF.TimeSpan:
  162. return XmlConvert.ToString ((TimeSpan) TypedValue);
  163. case BF.Guid:
  164. return XmlConvert.ToString ((Guid) TypedValue);
  165. case BF.UniqueId:
  166. return TypedValue.ToString ();
  167. case BF.Bytes8:
  168. case BF.Bytes16:
  169. case BF.Bytes32:
  170. return Convert.ToBase64String ((byte []) TypedValue);
  171. case BF.QNameIndex:
  172. return Name;
  173. default:
  174. throw new NotImplementedException ("ValueType " + ValueType + " on node " + NodeType);
  175. }
  176. }
  177. set { this.value = value; }
  178. }
  179. public virtual void Reset ()
  180. {
  181. Position = 0;
  182. DictLocalName = DictNS = null;
  183. LocalName = NS = Prefix = Value = name = String.Empty;
  184. NodeType = XmlNodeType.None;
  185. TypedValue = null;
  186. ValueType = 0;
  187. NSSlot = -1;
  188. }
  189. }
  190. class AttrNodeInfo : NodeInfo
  191. {
  192. public AttrNodeInfo (XmlBinaryDictionaryReader owner)
  193. {
  194. this.owner = owner;
  195. }
  196. XmlBinaryDictionaryReader owner;
  197. public int ValueIndex;
  198. public override void Reset ()
  199. {
  200. base.Reset ();
  201. ValueIndex = -1;
  202. NodeType = XmlNodeType.Attribute;
  203. }
  204. public override string Value {
  205. get { return owner.attr_values [ValueIndex].Value; }
  206. }
  207. }
  208. ISource source;
  209. IXmlDictionary dictionary;
  210. XmlDictionaryReaderQuotas quota;
  211. XmlBinaryReaderSession session;
  212. OnXmlDictionaryReaderClose on_close;
  213. XmlParserContext context;
  214. ReadState state = ReadState.Initial;
  215. NodeInfo node;
  216. NodeInfo current;
  217. List<AttrNodeInfo> attributes = new List<AttrNodeInfo> ();
  218. List<NodeInfo> attr_values = new List<NodeInfo> ();
  219. List<NodeInfo> node_stack = new List<NodeInfo> ();
  220. List<QName> ns_store = new List<QName> ();
  221. Dictionary<int,XmlDictionaryString> ns_dict_store =
  222. new Dictionary<int,XmlDictionaryString> ();
  223. int attr_count;
  224. int attr_value_count;
  225. int current_attr = -1;
  226. int depth = 0;
  227. // used during Read()
  228. int ns_slot;
  229. // next byte in the source (one byte token ahead always
  230. // happens because there is no "end of start element" mark).
  231. int next = -1;
  232. bool is_next_end_element;
  233. // temporary buffer for utf8enc.GetString()
  234. byte [] tmp_buffer = new byte [128];
  235. UTF8Encoding utf8enc = new UTF8Encoding ();
  236. // See comment at Read()
  237. int array_item_remaining;
  238. byte array_item_type;
  239. XmlNodeType array_state;
  240. public XmlBinaryDictionaryReader (byte [] buffer, int offset,
  241. int count, IXmlDictionary dictionary,
  242. XmlDictionaryReaderQuotas quota,
  243. XmlBinaryReaderSession session,
  244. OnXmlDictionaryReaderClose onClose)
  245. {
  246. source = /*new ArraySource (buffer, offset, count);*/
  247. new StreamSource (new MemoryStream (buffer, offset, count));
  248. Initialize (dictionary, quota, session, onClose);
  249. }
  250. public XmlBinaryDictionaryReader (Stream stream,
  251. IXmlDictionary dictionary,
  252. XmlDictionaryReaderQuotas quota,
  253. XmlBinaryReaderSession session,
  254. OnXmlDictionaryReaderClose onClose)
  255. {
  256. source = new StreamSource (stream);
  257. Initialize (dictionary, quota, session, onClose);
  258. }
  259. private void Initialize (IXmlDictionary dictionary,
  260. XmlDictionaryReaderQuotas quotas,
  261. XmlBinaryReaderSession session,
  262. OnXmlDictionaryReaderClose onClose)
  263. {
  264. if (quotas == null)
  265. throw new ArgumentNullException ("quotas");
  266. if (dictionary == null)
  267. dictionary = new XmlDictionary ();
  268. this.dictionary = dictionary;
  269. this.quota = quotas;
  270. if (session == null)
  271. session = new XmlBinaryReaderSession ();
  272. this.session = session;
  273. on_close = onClose;
  274. NameTable nt = new NameTable ();
  275. this.context = new XmlParserContext (nt,
  276. new XmlNamespaceManager (nt),
  277. null, XmlSpace.None);
  278. current = node = new NodeInfo ();
  279. current.Reset ();
  280. node_stack.Add (node);
  281. }
  282. public override int AttributeCount {
  283. get { return attr_count; }
  284. }
  285. public override string BaseURI {
  286. get { return context.BaseURI; }
  287. }
  288. public override int Depth {
  289. get { return current == node ? depth : NodeType == XmlNodeType.Attribute ? depth + 1 : depth + 2; }
  290. }
  291. public override bool EOF {
  292. get { return state == ReadState.EndOfFile || state == ReadState.Error; }
  293. }
  294. public override bool HasValue {
  295. get { return Value.Length > 0; }
  296. }
  297. public override bool IsEmptyElement {
  298. get { return false; }
  299. }
  300. public override XmlNodeType NodeType {
  301. get { return current.NodeType; }
  302. }
  303. public override string Prefix {
  304. get { return current_attr >= 0 ? attributes [current_attr].Prefix : current.Prefix; }
  305. }
  306. // looks like it may return attribute's name even if it is on its value node.
  307. public override string LocalName {
  308. get { return current_attr >= 0 ? attributes [current_attr].LocalName : current.LocalName; }
  309. }
  310. public override string Name {
  311. get { return current_attr >= 0 ? attributes [current_attr].Name : current.Name; }
  312. }
  313. public override string NamespaceURI {
  314. get { return current_attr >= 0 ? attributes [current_attr].NS : current.NS; }
  315. }
  316. public override XmlNameTable NameTable {
  317. get { return context.NameTable; }
  318. }
  319. public override XmlDictionaryReaderQuotas Quotas {
  320. get { return quota; }
  321. }
  322. public override ReadState ReadState {
  323. get { return state; }
  324. }
  325. public override string Value {
  326. get { return current.Value; }
  327. }
  328. public override void Close ()
  329. {
  330. if (on_close != null)
  331. on_close (this);
  332. }
  333. public override string GetAttribute (int i)
  334. {
  335. if (i >= attr_count)
  336. throw new ArgumentOutOfRangeException (String.Format ("Specified attribute index is {0} and should be less than {1}", i, attr_count));
  337. return attributes [i].Value;
  338. }
  339. public override string GetAttribute (string name)
  340. {
  341. for (int i = 0; i < attr_count; i++)
  342. if (attributes [i].Name == name)
  343. return attributes [i].Value;
  344. return null;
  345. }
  346. public override string GetAttribute (string localName, string ns)
  347. {
  348. for (int i = 0; i < attr_count; i++)
  349. if (attributes [i].LocalName == localName &&
  350. attributes [i].NS == ns)
  351. return attributes [i].Value;
  352. return null;
  353. }
  354. public IDictionary<string,string> GetNamespacesInScope (
  355. XmlNamespaceScope scope)
  356. {
  357. return context.NamespaceManager.GetNamespacesInScope (scope);
  358. }
  359. public string LookupPrefix (string ns)
  360. {
  361. return context.NamespaceManager.LookupPrefix (NameTable.Get (ns));
  362. }
  363. public override string LookupNamespace (string prefix)
  364. {
  365. return context.NamespaceManager.LookupNamespace (
  366. NameTable.Get (prefix));
  367. }
  368. public override bool IsArray (out Type type)
  369. {
  370. if (array_state == XmlNodeType.Element) {
  371. type = GetArrayType (array_item_type);
  372. return true;
  373. } else {
  374. type = null;
  375. return false;
  376. }
  377. }
  378. public override bool MoveToElement ()
  379. {
  380. bool ret = current_attr >= 0;
  381. current_attr = -1;
  382. current = node;
  383. return ret;
  384. }
  385. public override bool MoveToFirstAttribute ()
  386. {
  387. if (attr_count == 0)
  388. return false;
  389. current_attr = 0;
  390. current = attributes [current_attr];
  391. return true;
  392. }
  393. public override bool MoveToNextAttribute ()
  394. {
  395. if (++current_attr < attr_count) {
  396. current = attributes [current_attr];
  397. return true;
  398. } else {
  399. --current_attr;
  400. return false;
  401. }
  402. }
  403. public override void MoveToAttribute (int i)
  404. {
  405. if (i >= attr_count)
  406. throw new ArgumentOutOfRangeException (String.Format ("Specified attribute index is {0} and should be less than {1}", i, attr_count));
  407. current_attr = i;
  408. current = attributes [i];
  409. }
  410. public override bool MoveToAttribute (string name)
  411. {
  412. for (int i = 0; i < attributes.Count; i++) {
  413. if (attributes [i].Name == name) {
  414. MoveToAttribute (i);
  415. return true;
  416. }
  417. }
  418. return false;
  419. }
  420. public override bool MoveToAttribute (string localName, string ns)
  421. {
  422. for (int i = 0; i < attributes.Count; i++) {
  423. if (attributes [i].LocalName == localName &&
  424. attributes [i].NS == ns) {
  425. MoveToAttribute (i);
  426. return true;
  427. }
  428. }
  429. return false;
  430. }
  431. public override bool ReadAttributeValue ()
  432. {
  433. if (current_attr < 0)
  434. return false;
  435. int start = attributes [current_attr].ValueIndex;
  436. int end = current_attr + 1 == attr_count ? attr_value_count : attributes [current_attr + 1].ValueIndex;
  437. if (start == end)
  438. return false;
  439. if (!current.IsAttributeValue) {
  440. current = attr_values [start];
  441. return true;
  442. }
  443. // Actually there is no case for attribute whose value is split to more than two nodes. We could simplify the node structure.
  444. return false;
  445. }
  446. // When reading an array (0x03), it requires extraneously
  447. // complex procedure for XmlReader. First, it reads element,
  448. // type of operation and length of the items. And this XmlReader
  449. // has to return Element state. On the next Read(), it proceeds
  450. // to the value node of the first item of the array, so it
  451. // reads the value stream. On the next Read(), it proceeds to
  452. // EndElement, so it should not read anything from stream while
  453. // it has to move to the node state to EndElement.
  454. public override bool Read ()
  455. {
  456. switch (state) {
  457. case ReadState.Closed:
  458. case ReadState.EndOfFile:
  459. case ReadState.Error:
  460. return false;
  461. }
  462. // clear.
  463. state = ReadState.Interactive;
  464. MoveToElement ();
  465. attr_count = 0;
  466. attr_value_count = 0;
  467. ns_slot = 0;
  468. if (node.NodeType == XmlNodeType.Element) {
  469. // push element scope
  470. if (node_stack.Count <= ++depth) {
  471. if (depth == quota.MaxDepth)
  472. throw new XmlException (String.Format ("Binary XML stream quota exceeded. Depth must be less than {0}", quota.MaxDepth));
  473. node = new NodeInfo ();
  474. node_stack.Add (node);
  475. } else {
  476. node = node_stack [depth]; // reuse
  477. node.Reset ();
  478. }
  479. }
  480. current = node;
  481. if (is_next_end_element) {
  482. is_next_end_element = false;
  483. node.Reset ();
  484. ProcessEndElement ();
  485. return true;
  486. }
  487. // process array node after preparing node stack.
  488. switch (array_state) {
  489. case XmlNodeType.Element:
  490. ReadArrayItem ();
  491. return true;
  492. case XmlNodeType.Text:
  493. ShiftToArrayItemEndElement ();
  494. return true;
  495. case XmlNodeType.EndElement:
  496. if (--array_item_remaining == 0) {
  497. array_state = XmlNodeType.None;
  498. break;
  499. } else {
  500. ShiftToArrayItemElement ();
  501. return true;
  502. }
  503. }
  504. // array consumer does not expect Reset whlie it's on reading. So call it later than array check.
  505. node.Reset ();
  506. int ident = next >= 0 ? next : source.ReadByte ();
  507. next = -1;
  508. // check end of source.
  509. if (ident < 0) {
  510. state = ReadState.EndOfFile;
  511. current.Reset ();
  512. return false;
  513. }
  514. is_next_end_element = ident > 0x80 && (ident & 1) == 1;
  515. ident -= is_next_end_element ? 1 : 0;
  516. switch (ident) {
  517. case BF.EndElement:
  518. ProcessEndElement ();
  519. break;
  520. case BF.Comment:
  521. node.Value = ReadUTF8 ();
  522. node.ValueType = BF.Comment;
  523. node.NodeType = XmlNodeType.Comment;
  524. break;
  525. case BF.ElemString:
  526. case BF.ElemStringPrefix:
  527. case BF.ElemIndex:
  528. case BF.ElemIndexPrefix:
  529. ReadElementBinary ((byte) ident);
  530. break;
  531. case BF.Array:
  532. ident = ReadByteOrError ();
  533. ReadElementBinary ((byte) ident);
  534. ident = ReadByteOrError ();
  535. if (ident != 0x01)
  536. throw new XmlException (String.Format ("EndElement is expected after element in an array. The actual byte was {0:X} in hexadecimal", ident));
  537. ident = ReadByteOrError () - 1; // -1 becauseit contains EndElement
  538. VerifyValidArrayItemType (ident);
  539. if (ident < 0)
  540. throw new XmlException ("The stream has ended where the array item type is expected");
  541. array_item_type = (byte) ident;
  542. array_item_remaining = ReadVariantSize ();
  543. if (array_item_remaining > quota.MaxArrayLength)
  544. throw new Exception (String.Format ("Binary xml stream exceeded max array length quota. Items are {0} and should be less than quota.MaxArrayLength", quota.MaxArrayLength));
  545. array_state = XmlNodeType.Element;
  546. break;
  547. default:
  548. if (BF.PrefixNElemIndexStart <= ident && ident <= BF.PrefixNElemIndexEnd ||
  549. BF.PrefixNElemStringStart <= ident && ident <= BF.PrefixNElemStringEnd)
  550. goto case BF.ElemString;
  551. ReadTextOrValue ((byte) ident, node, false);
  552. break;
  553. }
  554. return true;
  555. }
  556. void ReadArrayItem ()
  557. {
  558. ReadTextOrValue (array_item_type, node, false);
  559. array_state = XmlNodeType.Text;
  560. }
  561. void ShiftToArrayItemEndElement ()
  562. {
  563. ProcessEndElement ();
  564. array_state = XmlNodeType.EndElement;
  565. }
  566. void ShiftToArrayItemElement ()
  567. {
  568. node.NodeType = XmlNodeType.Element;
  569. context.NamespaceManager.PushScope ();
  570. array_state = XmlNodeType.Element;
  571. }
  572. void VerifyValidArrayItemType (int ident)
  573. {
  574. if (GetArrayType (ident) == null)
  575. throw new XmlException (String.Format ("Unexpected array item type {0:X} in hexadecimal", ident));
  576. }
  577. Type GetArrayType (int ident)
  578. {
  579. switch (ident) {
  580. case BF.Bool:
  581. return typeof (bool);
  582. case BF.Int16:
  583. return typeof (short);
  584. case BF.Int32:
  585. return typeof (int);
  586. case BF.Int64:
  587. return typeof (long);
  588. case BF.Single:
  589. return typeof (float);
  590. case BF.Double:
  591. return typeof (double);
  592. case BF.Decimal:
  593. return typeof (decimal);
  594. case BF.DateTime:
  595. return typeof (DateTime);
  596. case BF.TimeSpan:
  597. return typeof (TimeSpan);
  598. case BF.Guid:
  599. return typeof (Guid);
  600. }
  601. return null;
  602. }
  603. private void ProcessEndElement ()
  604. {
  605. if (depth == 0)
  606. throw new XmlException ("Unexpected end of element while there is no element started.");
  607. current = node = node_stack [--depth];
  608. node.NodeType = XmlNodeType.EndElement;
  609. context.NamespaceManager.PopScope ();
  610. }
  611. private void ReadElementBinary (int ident)
  612. {
  613. // element
  614. node.NodeType = XmlNodeType.Element;
  615. node.Prefix = String.Empty;
  616. context.NamespaceManager.PushScope ();
  617. switch (ident) {
  618. case BF.ElemString:
  619. node.LocalName = ReadUTF8 ();
  620. break;
  621. case BF.ElemStringPrefix:
  622. node.Prefix = ReadUTF8 ();
  623. node.NSSlot = ns_slot++;
  624. goto case BF.ElemString;
  625. case BF.ElemIndex:
  626. node.DictLocalName = ReadDictName ();
  627. break;
  628. case BF.ElemIndexPrefix:
  629. node.Prefix = ReadUTF8 ();
  630. node.NSSlot = ns_slot++;
  631. goto case BF.ElemIndex;
  632. default:
  633. if (BF.PrefixNElemIndexStart <= ident && ident <= BF.PrefixNElemIndexEnd) {
  634. node.Prefix = ((char) (ident - BF.PrefixNElemIndexStart + 'a')).ToString ();
  635. node.DictLocalName = ReadDictName ();
  636. } else if (BF.PrefixNElemStringStart <= ident && ident <= BF.PrefixNElemStringEnd) {
  637. node.Prefix = ((char) (ident - BF.PrefixNElemStringStart + 'a')).ToString ();
  638. node.LocalName = ReadUTF8 ();
  639. }
  640. else
  641. throw new XmlException (String.Format ("Invalid element node type {0:X02} in hexadecimal", ident));
  642. break;
  643. }
  644. bool loop = true;
  645. do {
  646. ident = ReadByteOrError ();
  647. switch (ident) {
  648. case BF.AttrString:
  649. case BF.AttrStringPrefix:
  650. case BF.AttrIndex:
  651. case BF.AttrIndexPrefix:
  652. ReadAttribute ((byte) ident);
  653. break;
  654. case BF.DefaultNSString:
  655. case BF.PrefixNSString:
  656. case BF.DefaultNSIndex:
  657. case BF.PrefixNSIndex:
  658. ReadNamespace ((byte) ident);
  659. break;
  660. default:
  661. if (BF.PrefixNAttrStringStart <= ident && ident <= BF.PrefixNAttrStringEnd ||
  662. BF.PrefixNAttrIndexStart <= ident && ident <= BF.PrefixNAttrIndexEnd)
  663. ReadAttribute ((byte) ident);
  664. else {
  665. next = ident;
  666. loop = false;
  667. }
  668. break;
  669. }
  670. } while (loop);
  671. node.NS = context.NamespaceManager.LookupNamespace (node.Prefix) ?? String.Empty;
  672. foreach (AttrNodeInfo a in attributes)
  673. if (a.Prefix.Length > 0)
  674. a.NS = context.NamespaceManager.LookupNamespace (a.Prefix);
  675. ns_store.Clear ();
  676. ns_dict_store.Clear ();
  677. }
  678. private void ReadAttribute (byte ident)
  679. {
  680. if (attributes.Count == attr_count)
  681. attributes.Add (new AttrNodeInfo (this));
  682. AttrNodeInfo a = attributes [attr_count++];
  683. a.Reset ();
  684. a.Position = source.Position;
  685. switch (ident) {
  686. case BF.AttrString:
  687. a.LocalName = ReadUTF8 ();
  688. break;
  689. case BF.AttrStringPrefix:
  690. a.Prefix = ReadUTF8 ();
  691. a.NSSlot = ns_slot++;
  692. goto case BF.AttrString;
  693. case BF.AttrIndex:
  694. a.DictLocalName = ReadDictName ();
  695. break;
  696. case BF.AttrIndexPrefix:
  697. a.Prefix = ReadUTF8 ();
  698. a.NSSlot = ns_slot++;
  699. goto case BF.AttrIndex;
  700. default:
  701. if (BF.PrefixNAttrStringStart <= ident && ident <= BF.PrefixNAttrStringEnd) {
  702. a.Prefix = ((char) ('a' + ident - BF.PrefixNAttrStringStart)).ToString ();
  703. a.LocalName = ReadUTF8 ();
  704. break;
  705. }
  706. else if (BF.PrefixNAttrIndexStart <= ident && ident <= BF.PrefixNAttrIndexEnd) {
  707. a.Prefix = ((char) ('a' + ident - BF.PrefixNAttrIndexStart)).ToString ();
  708. a.DictLocalName = ReadDictName ();
  709. break;
  710. }
  711. else throw new XmlException (String.Format ("Unexpected attribute node type: 0x{0:X02}", ident));
  712. }
  713. ReadAttributeValueBinary (a);
  714. }
  715. private void ReadNamespace (byte ident)
  716. {
  717. // create attrubute slot.
  718. if (attributes.Count == attr_count)
  719. attributes.Add (new AttrNodeInfo (this));
  720. AttrNodeInfo a = attributes [attr_count++];
  721. a.Reset ();
  722. a.Position = source.Position;
  723. string prefix = null, ns = null;
  724. XmlDictionaryString dns = null;
  725. switch (ident) {
  726. case BF.DefaultNSString:
  727. prefix = String.Empty;
  728. ns = ReadUTF8 ();
  729. break;
  730. case BF.PrefixNSString:
  731. prefix = ReadUTF8 ();
  732. ns = ReadUTF8 ();
  733. break;
  734. case BF.DefaultNSIndex:
  735. prefix = String.Empty;
  736. dns = ReadDictName ();
  737. ns_dict_store.Add (ns_store.Count, dns);
  738. ns = dns.Value;
  739. break;
  740. case BF.PrefixNSIndex:
  741. prefix = ReadUTF8 ();
  742. dns = ReadDictName ();
  743. ns_dict_store.Add (ns_store.Count, dns);
  744. ns = dns.Value;
  745. break;
  746. }
  747. // fill attribute slot.
  748. a.Prefix = prefix.Length > 0 ? "xmlns" : String.Empty;
  749. a.LocalName = prefix.Length > 0 ? prefix : "xmlns";
  750. a.NS = "http://www.w3.org/2000/xmlns/";
  751. a.ValueIndex = attr_value_count;
  752. if (attr_value_count == attr_values.Count)
  753. attr_values.Add (new NodeInfo (true));
  754. NodeInfo v = attr_values [attr_value_count++];
  755. v.Reset ();
  756. v.Value = ns;
  757. v.ValueType = BF.Chars8;
  758. v.NodeType = XmlNodeType.Text;
  759. ns_store.Add (new QName (prefix, ns));
  760. context.NamespaceManager.AddNamespace (prefix, ns);
  761. }
  762. private void ReadAttributeValueBinary (AttrNodeInfo a)
  763. {
  764. a.ValueIndex = attr_value_count;
  765. if (attr_value_count == attr_values.Count)
  766. attr_values.Add (new NodeInfo (true));
  767. NodeInfo v = attr_values [attr_value_count++];
  768. v.Reset ();
  769. int ident = ReadByteOrError ();
  770. bool end = ident > 0x80 && (ident & 1) == 1;
  771. ident -= end ? 1 : 0;
  772. ReadTextOrValue ((byte) ident, v, true);
  773. }
  774. private bool ReadTextOrValue (byte ident, NodeInfo node, bool canSkip)
  775. {
  776. node.Value = null;
  777. node.ValueType = ident;
  778. node.NodeType = XmlNodeType.Text;
  779. switch (ident) {
  780. case BF.Zero:
  781. node.TypedValue = 0;
  782. break;
  783. case BF.One:
  784. node.TypedValue = 1;
  785. break;
  786. case BF.BoolFalse:
  787. node.TypedValue = false;
  788. break;
  789. case BF.BoolTrue:
  790. node.TypedValue = true;
  791. break;
  792. case BF.Int8:
  793. node.TypedValue = ReadByteOrError ();
  794. break;
  795. case BF.Int16:
  796. node.TypedValue = source.Reader.ReadInt16 ();
  797. break;
  798. case BF.Int32:
  799. node.TypedValue = source.Reader.ReadInt32 ();
  800. break;
  801. case BF.Int64:
  802. node.TypedValue = source.Reader.ReadInt64 ();
  803. break;
  804. case BF.Single:
  805. node.TypedValue = source.Reader.ReadSingle ();
  806. break;
  807. case BF.Double:
  808. node.TypedValue = source.Reader.ReadDouble ();
  809. break;
  810. case BF.Decimal:
  811. int [] bits = new int [4];
  812. bits [3] = source.Reader.ReadInt32 ();
  813. bits [2] = source.Reader.ReadInt32 ();
  814. bits [0] = source.Reader.ReadInt32 ();
  815. bits [1] = source.Reader.ReadInt32 ();
  816. node.TypedValue = new Decimal (bits);
  817. break;
  818. case BF.DateTime:
  819. node.TypedValue = DateTime.FromBinary (source.Reader.ReadInt64 ());
  820. break;
  821. //case BF.UniqueId: // identical to .Text
  822. case BF.Bytes8:
  823. case BF.Bytes16:
  824. case BF.Bytes32:
  825. int size =
  826. (ident == BF.Bytes8) ? source.Reader.ReadByte () :
  827. (ident == BF.Bytes16) ? source.Reader.ReadUInt16 () :
  828. source.Reader.ReadInt32 ();
  829. byte [] base64 = Alloc (size);
  830. source.Reader.Read (base64, 0, base64.Length);
  831. node.TypedValue = base64;
  832. break;
  833. case BF.TimeSpan:
  834. node.TypedValue = new TimeSpan (source.Reader.ReadInt64 ());
  835. break;
  836. case BF.UniqueId:
  837. byte [] guid = new byte [16];
  838. source.Reader.Read (guid, 0, guid.Length);
  839. node.TypedValue = new UniqueId (new Guid (guid));
  840. break;
  841. case BF.Guid:
  842. guid = new byte [16];
  843. source.Reader.Read (guid, 0, guid.Length);
  844. node.TypedValue = new Guid (guid);
  845. break;
  846. case BF.Chars8:
  847. case BF.Chars16:
  848. case BF.Chars32:
  849. case BF.Utf16_8:
  850. case BF.Utf16_16:
  851. case BF.Utf16_32:
  852. Encoding enc = ident <= BF.Chars32 ? Encoding.UTF8 : Encoding.Unicode;
  853. size =
  854. (ident == BF.Chars8 || ident == BF.Utf16_8) ? source.Reader.ReadByte () :
  855. (ident == BF.Chars16 || ident == BF.Utf16_16) ? source.Reader.ReadUInt16 () :
  856. source.Reader.ReadInt32 ();
  857. byte [] bytes = Alloc (size);
  858. source.Reader.Read (bytes, 0, size);
  859. node.Value = enc.GetString (bytes, 0, size);
  860. node.NodeType = XmlNodeType.Text;
  861. break;
  862. case BF.EmptyText:
  863. node.Value = String.Empty;
  864. node.NodeType = XmlNodeType.Text;
  865. break;
  866. case BF.TextIndex:
  867. node.DictValue = ReadDictName ();
  868. node.NodeType = XmlNodeType.Text;
  869. break;
  870. case BF.QNameIndex:
  871. node.Prefix = ((char) (ReadByteOrError () + 'a')).ToString ();
  872. node.DictLocalName = ReadDictName();
  873. break;
  874. default:
  875. if (!canSkip)
  876. throw new ArgumentException (String.Format ("Unexpected binary XML data at position {1}: {0:X}", ident + (is_next_end_element ? 1 : 0), source.Position));
  877. next = ident;
  878. return false;
  879. }
  880. return true;
  881. }
  882. byte [] Alloc (int size)
  883. {
  884. if (size > quota.MaxStringContentLength || size < 0)
  885. throw new XmlException (String.Format ("Text content buffer exceeds the quota limitation at {2}. {0} bytes and should be less than {1} bytes", size, quota.MaxStringContentLength, source.Position));
  886. return new byte [size];
  887. }
  888. private int ReadVariantSize ()
  889. {
  890. int size = 0;
  891. // If sizeSpec < 0, then it is variant size specifier.
  892. // Otherwise it is fixed size s = sizeSpec + 1 byte(s).
  893. int d = 0;
  894. do {
  895. byte got = ReadByteOrError ();
  896. size += (got & 0x7F) << d;
  897. d += 7;
  898. if (got < 0x80)
  899. break;
  900. } while (true);
  901. return size;
  902. }
  903. private string ReadUTF8 ()
  904. {
  905. int size = ReadVariantSize ();
  906. if (size == 0)
  907. return String.Empty;
  908. if (tmp_buffer.Length < size) {
  909. int extlen = tmp_buffer.Length * 2;
  910. tmp_buffer = Alloc (size < extlen ? extlen : size);
  911. }
  912. size = source.Read (tmp_buffer, 0, size);
  913. return utf8enc.GetString (tmp_buffer, 0, size);
  914. }
  915. private XmlDictionaryString ReadDictName ()
  916. {
  917. int key = ReadVariantSize ();
  918. XmlDictionaryString s;
  919. if ((key & 1) == 1) {
  920. if (session.TryLookup (key >> 1, out s))
  921. return s;
  922. } else {
  923. if (dictionary.TryLookup (key >> 1, out s))
  924. return s;
  925. }
  926. throw new XmlException (String.Format ("Input XML binary stream is invalid. No matching XML dictionary string entry at {0}. Binary stream position at {1}", key, source.Position));
  927. }
  928. private byte ReadByteOrError ()
  929. {
  930. if (next >= 0) {
  931. byte b = (byte) next;
  932. next = -1;
  933. return b;
  934. }
  935. int ret = source.ReadByte ();
  936. if (ret < 0)
  937. throw new XmlException (String.Format ("Unexpected end of binary stream. Position is at {0}", source.Position));
  938. return (byte) ret;
  939. }
  940. public override void ResolveEntity ()
  941. {
  942. throw new NotSupportedException ("this XmlReader does not support ResolveEntity.");
  943. }
  944. public override bool TryGetBase64ContentLength (out int length)
  945. {
  946. length = 0;
  947. switch (current.ValueType) {
  948. case BF.Bytes8:
  949. case BF.Bytes16:
  950. case BF.Bytes32:
  951. length = ((byte []) current.TypedValue).Length;
  952. return true;
  953. }
  954. return false;
  955. }
  956. public override string ReadContentAsString ()
  957. {
  958. string value = String.Empty;
  959. do {
  960. switch (NodeType) {
  961. case XmlNodeType.Element:
  962. case XmlNodeType.EndElement:
  963. return value;
  964. case XmlNodeType.Text:
  965. value += Value;
  966. break;
  967. }
  968. } while (Read ());
  969. return value;
  970. }
  971. #region read typed content
  972. public override int ReadContentAsInt ()
  973. {
  974. int ret = GetIntValue ();
  975. Read ();
  976. return ret;
  977. }
  978. int GetIntValue ()
  979. {
  980. switch (node.ValueType) {
  981. case BF.Zero:
  982. return 0;
  983. case BF.One:
  984. return 1;
  985. case BF.Int8:
  986. return (byte) current.TypedValue;
  987. case BF.Int16:
  988. return (short) current.TypedValue;
  989. case BF.Int32:
  990. return (int) current.TypedValue;
  991. }
  992. throw new InvalidOperationException (String.Format ("Current content is not an integer. (Internal value type:{0:X02})", (int) node.ValueType));
  993. }
  994. public override long ReadContentAsLong ()
  995. {
  996. if (node.ValueType == BF.Int64) {
  997. long v = (long) current.TypedValue;
  998. Read ();
  999. return v;
  1000. }
  1001. return ReadContentAsInt ();
  1002. }
  1003. public override float ReadContentAsFloat ()
  1004. {
  1005. if (node.ValueType != BF.Single)
  1006. throw new InvalidOperationException ("Current content is not a single");
  1007. float v = (float) current.TypedValue;
  1008. Read ();
  1009. return v;
  1010. }
  1011. public override double ReadContentAsDouble ()
  1012. {
  1013. if (node.ValueType != BF.Double)
  1014. throw new InvalidOperationException ("Current content is not a double");
  1015. double v = (double) current.TypedValue;
  1016. Read ();
  1017. return v;
  1018. }
  1019. bool IsBase64Node (byte b)
  1020. {
  1021. switch (b) {
  1022. case BF.Bytes8:
  1023. case BF.Bytes16:
  1024. case BF.Bytes32:
  1025. return true;
  1026. }
  1027. return false;
  1028. }
  1029. // FIXME: this is not likely to consume sequential base64 nodes.
  1030. public override byte [] ReadContentAsBase64 ()
  1031. {
  1032. byte [] ret = null;
  1033. if (!IsBase64Node (node.ValueType))
  1034. throw new InvalidOperationException ("Current content is not base64");
  1035. while (NodeType == XmlNodeType.Text && IsBase64Node (node.ValueType)) {
  1036. if (ret == null)
  1037. ret = (byte []) node.TypedValue;
  1038. else {
  1039. byte [] tmp = (byte []) node.TypedValue;
  1040. byte [] tmp2 = Alloc (ret.Length + tmp.Length);
  1041. Array.Copy (ret, tmp2, ret.Length);
  1042. Array.Copy (tmp, 0, tmp2, ret.Length, tmp.Length);
  1043. ret = tmp2;
  1044. }
  1045. Read ();
  1046. //MoveToContent ();
  1047. }
  1048. return ret;
  1049. }
  1050. public override Guid ReadContentAsGuid ()
  1051. {
  1052. if (node.ValueType != BF.Guid)
  1053. throw new InvalidOperationException ("Current content is not a Guid");
  1054. Guid ret = (Guid) node.TypedValue;
  1055. Read ();
  1056. return ret;
  1057. }
  1058. public override UniqueId ReadContentAsUniqueId ()
  1059. {
  1060. switch (node.ValueType) {
  1061. case BF.Chars8:
  1062. case BF.Chars16:
  1063. case BF.Chars32:
  1064. case BF.Utf16_8:
  1065. case BF.Utf16_16:
  1066. case BF.Utf16_32:
  1067. UniqueId ret = new UniqueId (node.Value);
  1068. Read ();
  1069. return ret;
  1070. case BF.UniqueId:
  1071. ret = (UniqueId) node.TypedValue;
  1072. Read ();
  1073. return ret;
  1074. default:
  1075. throw new InvalidOperationException ("Current content is not a UniqueId");
  1076. }
  1077. }
  1078. #endregion
  1079. }
  1080. }