XmlBinaryDictionaryReader.cs 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114
  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. // - native value data (7B-82, 8D-A0) are not implemented.
  42. // - support XmlDictionaryReaderQuotas.
  43. // - support XmlBinaryReaderSession.
  44. // - handle namespaces as expected.
  45. internal class XmlBinaryDictionaryReader : XmlDictionaryReader, IXmlNamespaceResolver
  46. {
  47. internal interface ISource
  48. {
  49. int Position { get; }
  50. int ReadByte ();
  51. int Read (byte [] data, int offset, int count);
  52. BinaryReader Reader { get; }
  53. }
  54. internal class StreamSource : ISource
  55. {
  56. BinaryReader stream;
  57. int position;
  58. public StreamSource (Stream stream)
  59. {
  60. this.stream = new BinaryReader (stream);
  61. }
  62. public int Position {
  63. get { return position - 1; }
  64. }
  65. public BinaryReader Reader {
  66. get { return stream; }
  67. }
  68. public int ReadByte ()
  69. {
  70. if (stream.PeekChar () < 0)
  71. return -1;
  72. position++;
  73. return stream.ReadByte ();
  74. }
  75. public int Read (byte [] data, int offset, int count)
  76. {
  77. int ret = stream.Read (data, offset, count);
  78. position += ret;
  79. return ret;
  80. }
  81. }
  82. class NodeInfo
  83. {
  84. public NodeInfo ()
  85. {
  86. }
  87. public NodeInfo (bool isAttr)
  88. {
  89. IsAttributeValue = isAttr;
  90. }
  91. public bool IsAttributeValue;
  92. public int Position;
  93. public string Prefix;
  94. public XmlDictionaryString DictLocalName;
  95. public XmlDictionaryString DictNS;
  96. public XmlNodeType NodeType;
  97. public object TypedValue;
  98. public byte ValueType;
  99. // -1 for nothing,
  100. // -2 for that of element (only for attribute),
  101. // 0 or more to fill later
  102. public int NSSlot;
  103. string name;
  104. string local_name;
  105. string ns;
  106. string value;
  107. public string LocalName {
  108. get { return DictLocalName != null ? DictLocalName.Value : local_name; }
  109. set {
  110. DictLocalName = null;
  111. local_name = value;
  112. }
  113. }
  114. public string NS {
  115. get { return DictNS != null ? DictNS.Value : ns; }
  116. set {
  117. DictNS = null;
  118. ns = value;
  119. }
  120. }
  121. public string Name {
  122. get {
  123. if (name == null)
  124. name = Prefix.Length > 0 ?
  125. String.Concat (Prefix, ":", LocalName) :
  126. LocalName;
  127. return name;
  128. }
  129. }
  130. public string Value {
  131. get {
  132. if (BF.AttrString <= ValueType && ValueType <= BF.GlobalAttrIndexInElemNS)
  133. return value; // attribute
  134. switch (ValueType) {
  135. case 0:
  136. case BF.Comment:
  137. case BF.Text:
  138. case BF.EmptyText:
  139. return value;
  140. case BF.Zero:
  141. case BF.One:
  142. return XmlConvert.ToString ((int) TypedValue);
  143. case BF.Int8:
  144. return XmlConvert.ToString ((byte) TypedValue);
  145. case BF.Int16:
  146. return XmlConvert.ToString ((short) TypedValue);
  147. case BF.Int32:
  148. return XmlConvert.ToString ((int) TypedValue);
  149. case BF.Int64:
  150. return XmlConvert.ToString ((long) TypedValue);
  151. case BF.Single:
  152. return XmlConvert.ToString ((float) TypedValue);
  153. case BF.Double:
  154. return XmlConvert.ToString ((double) TypedValue);
  155. case BF.DateTime:
  156. return XmlConvert.ToString ((DateTime) TypedValue, XmlDateTimeSerializationMode.RoundtripKind);
  157. case BF.TimeSpan:
  158. return XmlConvert.ToString ((TimeSpan) TypedValue);
  159. case BF.Guid:
  160. return XmlConvert.ToString ((Guid) TypedValue);
  161. case BF.UniqueIdFromGuid:
  162. return TypedValue.ToString ();
  163. case BF.Base64:
  164. case BF.Base64Fixed:
  165. return Convert.ToBase64String ((byte []) TypedValue);
  166. default:
  167. throw new NotImplementedException ("ValueType " + ValueType + " on node " + NodeType);
  168. }
  169. }
  170. set { this.value = value; }
  171. }
  172. public virtual void Reset ()
  173. {
  174. Position = 0;
  175. DictLocalName = DictNS = null;
  176. LocalName = NS = Prefix = Value = String.Empty;
  177. NodeType = XmlNodeType.None;
  178. TypedValue = null;
  179. ValueType = 0;
  180. NSSlot = -1;
  181. }
  182. }
  183. class AttrNodeInfo : NodeInfo
  184. {
  185. public int ValueIndex;
  186. public override void Reset ()
  187. {
  188. base.Reset ();
  189. ValueIndex = -1;
  190. }
  191. }
  192. ISource source;
  193. IXmlDictionary dictionary;
  194. XmlDictionaryReaderQuotas quota;
  195. XmlBinaryReaderSession session;
  196. OnXmlDictionaryReaderClose on_close;
  197. XmlParserContext context;
  198. ReadState state = ReadState.Initial;
  199. NodeInfo node;
  200. NodeInfo current;
  201. List<AttrNodeInfo> attributes = new List<AttrNodeInfo> ();
  202. List<NodeInfo> attr_values = new List<NodeInfo> ();
  203. List<NodeInfo> node_stack = new List<NodeInfo> ();
  204. List<QName> ns_store = new List<QName> ();
  205. Dictionary<int,XmlDictionaryString> ns_dict_store =
  206. new Dictionary<int,XmlDictionaryString> ();
  207. int attr_count;
  208. int attr_value_count;
  209. int current_attr = -1;
  210. int depth = 0;
  211. // used during Read()
  212. int ns_slot;
  213. // next byte in the source (one byte token ahead always
  214. // happens because there is no "end of start element" mark).
  215. int next = -1;
  216. bool is_next_end_element;
  217. // temporary buffer for utf8enc.GetString()
  218. byte [] tmp_buffer = new byte [128];
  219. UTF8Encoding utf8enc = new UTF8Encoding ();
  220. public XmlBinaryDictionaryReader (byte [] buffer, int offset,
  221. int count, IXmlDictionary dictionary,
  222. XmlDictionaryReaderQuotas quota,
  223. XmlBinaryReaderSession session,
  224. OnXmlDictionaryReaderClose onClose)
  225. {
  226. source = /*new ArraySource (buffer, offset, count);*/
  227. new StreamSource (new MemoryStream (buffer, offset, count));
  228. Initialize (dictionary, quota, session, onClose);
  229. }
  230. public XmlBinaryDictionaryReader (Stream stream,
  231. IXmlDictionary dictionary,
  232. XmlDictionaryReaderQuotas quota,
  233. XmlBinaryReaderSession session,
  234. OnXmlDictionaryReaderClose onClose)
  235. {
  236. source = new StreamSource (stream);
  237. Initialize (dictionary, quota, session, onClose);
  238. }
  239. private void Initialize (IXmlDictionary dictionary,
  240. XmlDictionaryReaderQuotas quotas,
  241. XmlBinaryReaderSession session,
  242. OnXmlDictionaryReaderClose onClose)
  243. {
  244. if (quotas == null)
  245. throw new ArgumentNullException ("quotas");
  246. if (dictionary == null)
  247. dictionary = new XmlDictionary ();
  248. this.dictionary = dictionary;
  249. this.quota = quotas;
  250. if (session == null)
  251. session = new XmlBinaryReaderSession ();
  252. this.session = session;
  253. on_close = onClose;
  254. NameTable nt = new NameTable ();
  255. this.context = new XmlParserContext (nt,
  256. new XmlNamespaceManager (nt),
  257. null, XmlSpace.None);
  258. current = node = new NodeInfo ();
  259. current.Reset ();
  260. }
  261. public override int AttributeCount {
  262. get { return attr_count; }
  263. }
  264. public override string BaseURI {
  265. get { return context.BaseURI; }
  266. }
  267. public override int Depth {
  268. get { return depth; }
  269. }
  270. public override bool EOF {
  271. get { return state == ReadState.EndOfFile || state == ReadState.Error; }
  272. }
  273. public override bool HasValue {
  274. get { return current.Value.Length > 0; }
  275. }
  276. public override bool IsEmptyElement {
  277. get { return false; }
  278. }
  279. public override XmlNodeType NodeType {
  280. get { return current.NodeType; }
  281. }
  282. public override string Prefix {
  283. get { return current.Prefix; }
  284. }
  285. public override string LocalName {
  286. get { return current.LocalName; }
  287. }
  288. public override string NamespaceURI {
  289. get { return current.NS; }
  290. }
  291. public override XmlNameTable NameTable {
  292. get { return context.NameTable; }
  293. }
  294. public override XmlDictionaryReaderQuotas Quotas {
  295. get { return quota; }
  296. }
  297. public override ReadState ReadState {
  298. get { return state; }
  299. }
  300. public override string Value {
  301. get { return current.Value; }
  302. }
  303. public override void Close ()
  304. {
  305. if (on_close != null)
  306. on_close (this);
  307. }
  308. public override string GetAttribute (int i)
  309. {
  310. if (i >= attr_count)
  311. throw new ArgumentOutOfRangeException (String.Format ("Specified attribute index is {0} and should be less than {1}", i, attr_count));
  312. return attributes [i].Value;
  313. }
  314. public override string GetAttribute (string name)
  315. {
  316. for (int i = 0; i < attributes.Count; i++)
  317. if (attributes [i].Name == name)
  318. return attributes [i].Value;
  319. return null;
  320. }
  321. public override string GetAttribute (string localName, string ns)
  322. {
  323. for (int i = 0; i < attributes.Count; i++)
  324. if (attributes [i].LocalName == localName &&
  325. attributes [i].NS == ns)
  326. return attributes [i].Value;
  327. return null;
  328. }
  329. public IDictionary<string,string> GetNamespacesInScope (
  330. XmlNamespaceScope scope)
  331. {
  332. return context.NamespaceManager.GetNamespacesInScope (scope);
  333. }
  334. public string LookupPrefix (string ns)
  335. {
  336. return context.NamespaceManager.LookupPrefix (NameTable.Get (ns));
  337. }
  338. public override string LookupNamespace (string prefix)
  339. {
  340. return context.NamespaceManager.LookupNamespace (
  341. NameTable.Get (prefix));
  342. }
  343. public override bool MoveToElement ()
  344. {
  345. bool ret = current_attr >= 0;
  346. current_attr = -1;
  347. current = node;
  348. return ret;
  349. }
  350. public override bool MoveToFirstAttribute ()
  351. {
  352. if (attr_count == 0)
  353. return false;
  354. current_attr = 0;
  355. current = attributes [current_attr];
  356. return true;
  357. }
  358. public override bool MoveToNextAttribute ()
  359. {
  360. if (++current_attr < attr_count) {
  361. current = attributes [current_attr];
  362. return true;
  363. } else {
  364. --current_attr;
  365. return false;
  366. }
  367. }
  368. public override void MoveToAttribute (int i)
  369. {
  370. if (i >= attr_count)
  371. throw new ArgumentOutOfRangeException (String.Format ("Specified attribute index is {0} and should be less than {1}", i, attr_count));
  372. current_attr = i;
  373. current = attributes [i];
  374. }
  375. public override bool MoveToAttribute (string name)
  376. {
  377. for (int i = 0; i < attributes.Count; i++) {
  378. if (attributes [i].Name == name) {
  379. MoveToAttribute (i);
  380. return true;
  381. }
  382. }
  383. return false;
  384. }
  385. public override bool MoveToAttribute (string localName, string ns)
  386. {
  387. for (int i = 0; i < attributes.Count; i++) {
  388. if (attributes [i].LocalName == localName &&
  389. attributes [i].NS == ns) {
  390. MoveToAttribute (i);
  391. return true;
  392. }
  393. }
  394. return false;
  395. }
  396. public override bool ReadAttributeValue ()
  397. {
  398. if (current_attr < 0)
  399. return false;
  400. int start = attributes [current_attr].ValueIndex;
  401. int end = current_attr + 1 == attr_count ? attr_value_count : attributes [current_attr + 1].ValueIndex;
  402. if (start == end)
  403. return false;
  404. if (!current.IsAttributeValue) {
  405. current = attr_values [start];
  406. return true;
  407. }
  408. for (int i = start; i < end; i++) {
  409. if (current == attr_values [i] && i + 1 < end) {
  410. current = attr_values [i + 1];
  411. return true;
  412. }
  413. }
  414. return false;
  415. }
  416. public override bool Read ()
  417. {
  418. switch (state) {
  419. case ReadState.Closed:
  420. case ReadState.EndOfFile:
  421. case ReadState.Error:
  422. return false;
  423. }
  424. // clear.
  425. state = ReadState.Interactive;
  426. attr_count = 0;
  427. attr_value_count = 0;
  428. ns_slot = 0;
  429. current = node;
  430. if (node.NodeType == XmlNodeType.Element) {
  431. // push element scope
  432. depth++;
  433. if (node_stack.Count <= depth) {
  434. node_stack.Add (node);
  435. node = new NodeInfo ();
  436. }
  437. else
  438. node = node_stack [depth];
  439. node.Reset ();
  440. current = node;
  441. }
  442. if (is_next_end_element) {
  443. is_next_end_element = false;
  444. ProcessEndElement ();
  445. return true;
  446. }
  447. node.Reset ();
  448. int ident = next >= 0 ? next : source.ReadByte ();
  449. next = -1;
  450. // check end of source.
  451. if (ident < 0) {
  452. state = ReadState.EndOfFile;
  453. current.Reset ();
  454. return false;
  455. }
  456. is_next_end_element = ident > 0x80 && (ident & 1) == 1;
  457. ident -= is_next_end_element ? 1 : 0;
  458. /*
  459. if (0x3F <= ident && ident <= 0x42)
  460. ReadElementBinary ((byte) ident);
  461. else {
  462. switch (ident) {
  463. case 0x3C: // end element
  464. ProcessEndElement ();
  465. break;
  466. case 0x3D: // comment
  467. node.Value = ReadUTF8 ();
  468. node.NodeType = XmlNodeType.Comment;
  469. break;
  470. default:
  471. ReadTextOrValue ((byte) ident, node, false);
  472. break;
  473. }
  474. }
  475. */
  476. switch (ident) {
  477. case BF.EndElement:
  478. ProcessEndElement ();
  479. break;
  480. case BF.Comment:
  481. node.Value = ReadUTF8 ();
  482. node.ValueType = BF.Comment;
  483. node.NodeType = XmlNodeType.Comment;
  484. break;
  485. case BF.ElemString:
  486. case BF.ElemStringPrefix:
  487. case BF.ElemIndex:
  488. case BF.ElemIndexPrefix:
  489. ReadElementBinary ((byte) ident);
  490. break;
  491. default:
  492. ReadTextOrValue ((byte) ident, node, false);
  493. break;
  494. }
  495. return true;
  496. }
  497. private void ProcessEndElement ()
  498. {
  499. if (depth == 0)
  500. throw new XmlException ("Unexpected end of element while there is no element started.");
  501. current = node = node_stack [--depth];
  502. node.NodeType = XmlNodeType.EndElement;
  503. context.NamespaceManager.PopScope ();
  504. }
  505. private void ReadElementBinary (int ident)
  506. {
  507. // element
  508. node.NodeType = XmlNodeType.Element;
  509. node.Prefix = String.Empty;
  510. context.NamespaceManager.PushScope ();
  511. switch (ident) {
  512. case BF.ElemString:
  513. node.LocalName = ReadUTF8 ();
  514. break;
  515. case BF.ElemStringPrefix:
  516. node.Prefix = ReadUTF8 ();
  517. node.NSSlot = ns_slot++;
  518. goto case BF.ElemString;
  519. case BF.ElemIndex:
  520. node.DictLocalName = ReadDictName ();
  521. break;
  522. case BF.ElemIndexPrefix:
  523. node.Prefix = ReadUTF8 ();
  524. node.NSSlot = ns_slot++;
  525. goto case BF.ElemIndex;
  526. }
  527. bool loop = true;
  528. do {
  529. ident = next < 0 ? ReadByteOrError () : next;
  530. next = -1;
  531. switch (ident) {
  532. case BF.AttrString:
  533. case BF.AttrStringPrefix:
  534. case BF.AttrIndex:
  535. case BF.AttrIndexPrefix:
  536. case BF.GlobalAttrIndex:
  537. case BF.GlobalAttrIndexInElemNS:
  538. ReadAttribute ((byte) ident);
  539. break;
  540. case BF.DefaultNSString:
  541. case BF.PrefixNSString:
  542. case BF.DefaultNSIndex:
  543. case BF.PrefixNSIndex:
  544. ReadNamespace ((byte) ident);
  545. break;
  546. default:
  547. next = ident;
  548. loop = false;
  549. break;
  550. }
  551. /*
  552. if (ident < 4) {
  553. // attributes
  554. if (attributes.Count == attr_count)
  555. attributes.Add (new AttrNodeInfo ());
  556. AttrNodeInfo a = attributes [attr_count++];
  557. a.Reset ();
  558. a.Position = source.Position;
  559. switch (ident) {
  560. case 0:
  561. a.LocalName = ReadUTF8 ();
  562. break;
  563. case 1:
  564. a.Prefix = ReadUTF8 ();
  565. goto case 0;
  566. case 2:
  567. a.DictLocalName = ReadDictName ();
  568. break;
  569. case 3:
  570. a.Prefix = ReadUTF8 ();
  571. goto case 2;
  572. }
  573. ReadAttributeValueBinary (a);
  574. }
  575. else if (ident < 6) {
  576. // namespaces
  577. string prefix = ident == 4 ?
  578. String.Empty : ReadUTF8 ();
  579. string ns = ReadUTF8 ();
  580. ns_store.Add (new QName (prefix, ns));
  581. context.NamespaceManager.AddNamespace (prefix, ns);
  582. }
  583. else if (0x22 <= ident && ident < 0x3C) {
  584. // attributes with predefined ns index
  585. if (attributes.Count == attr_count)
  586. attributes.Add (new AttrNodeInfo ());
  587. AttrNodeInfo a = attributes [attr_count++];
  588. a.Reset ();
  589. a.Position = source.Position;
  590. a.NSSlot = ident - 0x22;
  591. a.LocalName = ReadUTF8 ();
  592. ReadAttributeValueBinary (a);
  593. }
  594. else {
  595. next = ident;
  596. break;
  597. }
  598. */
  599. } while (loop);
  600. #if true
  601. node.NS = context.NamespaceManager.LookupNamespace (node.Prefix) ?? String.Empty;
  602. foreach (AttrNodeInfo a in attributes)
  603. if (a.Prefix.Length > 0)
  604. a.NS = context.NamespaceManager.LookupNamespace (a.Prefix);
  605. //Console.WriteLine ("[{0}-{1}->{3}/{2:X02}]", node.Prefix, node.LocalName, ident, node.NS);
  606. #else
  607. if (node.Prefix.Length == 0)
  608. foreach (QName q in ns_store)
  609. if (q.Name.Length == 0) {
  610. node.NS = q.Namespace;
  611. break;
  612. }
  613. else if (node.NSSlot >= 0)
  614. FillNamespaceBySlot (node);
  615. foreach (AttrNodeInfo a in attributes) {
  616. if (a.NSSlot >= 0) {
  617. /*
  618. if (a.NSSlot >= ns_store.Count)
  619. throw new XmlException (String.Format ("Binary XML data is not valid. An attribute node has an invalid index at position {0}. Index is {1}.", a.Position, a.NSSlot));
  620. a.NS = ns_store [a.NSSlot].Namespace;
  621. a.Prefix = ns_store [a.NSSlot].Name;
  622. */
  623. FillNamespaceBySlot (a);
  624. }
  625. else if (a.NSSlot == -2) {
  626. a.NS = node.NS;
  627. a.Prefix = node.Prefix;
  628. }
  629. }
  630. #endif
  631. ns_store.Clear ();
  632. ns_dict_store.Clear ();
  633. }
  634. void FillNamespaceBySlot (NodeInfo n)
  635. {
  636. if (n.NSSlot >= ns_store.Count)
  637. throw new XmlException (String.Format ("Binary XML data is not valid. The '{2}' node has an invalid index. Index is {1}. The position in the stream is at {0}.", n.Position, n.NSSlot, n.NodeType));
  638. n.NS = ns_store [n.NSSlot].Namespace;
  639. //n.Prefix = ns_store [n.NSSlot].Name;
  640. }
  641. private void ReadAttribute (byte ident)
  642. {
  643. if (attributes.Count == attr_count)
  644. attributes.Add (new AttrNodeInfo ());
  645. AttrNodeInfo a = attributes [attr_count++];
  646. a.Reset ();
  647. a.Position = source.Position;
  648. switch (ident) {
  649. case BF.AttrString:
  650. a.LocalName = ReadUTF8 ();
  651. break;
  652. case BF.AttrStringPrefix:
  653. a.Prefix = ReadUTF8 ();
  654. a.NSSlot = ns_slot++;
  655. goto case BF.AttrString;
  656. case BF.AttrIndex:
  657. a.DictLocalName = ReadDictName ();
  658. break;
  659. case BF.AttrIndexPrefix:
  660. a.Prefix = ReadUTF8 ();
  661. a.NSSlot = ns_slot++;
  662. goto case BF.AttrIndex;
  663. case BF.GlobalAttrIndex:
  664. a.NSSlot = ns_slot++;
  665. a.DictLocalName = ReadDictName ();
  666. // FIXME: retrieve namespace
  667. break;
  668. case BF.GlobalAttrIndexInElemNS:
  669. a.Prefix = node.Prefix;
  670. a.DictLocalName = ReadDictName ();
  671. a.NSSlot = -2;
  672. break;
  673. }
  674. ReadAttributeValueBinary (a);
  675. }
  676. private void ReadNamespace (byte ident)
  677. {
  678. string prefix = null, ns = null;
  679. XmlDictionaryString dns;
  680. switch (ident) {
  681. case BF.DefaultNSString:
  682. prefix = String.Empty;
  683. ns = ReadUTF8 ();
  684. break;
  685. case BF.PrefixNSString:
  686. prefix = ReadUTF8 ();
  687. ns = ReadUTF8 ();
  688. break;
  689. case BF.DefaultNSIndex:
  690. prefix = String.Empty;
  691. dns = ReadDictName ();
  692. ns_dict_store.Add (ns_store.Count, dns);
  693. ns = dns.Value;
  694. break;
  695. case BF.PrefixNSIndex:
  696. prefix = ReadUTF8 ();
  697. dns = ReadDictName ();
  698. ns_dict_store.Add (ns_store.Count, dns);
  699. ns = dns.Value;
  700. break;
  701. }
  702. ns_store.Add (new QName (prefix, ns));
  703. context.NamespaceManager.AddNamespace (prefix, ns);
  704. }
  705. private void ReadAttributeValueBinary (AttrNodeInfo a)
  706. {
  707. a.ValueIndex = attr_value_count;
  708. do {
  709. if (attr_value_count == attr_values.Count)
  710. attr_values.Add (new NodeInfo (true));
  711. NodeInfo v = attr_values [attr_value_count++];
  712. v.Reset ();
  713. int ident = ReadByteOrError ();
  714. is_next_end_element = ident > 0x80 && (ident & 1) == 1;
  715. ident -= is_next_end_element ? 1 : 0;
  716. if (!ReadTextOrValue ((byte) ident, v, true) || is_next_end_element)
  717. break;
  718. } while (true);
  719. }
  720. private bool ReadTextOrValue (byte ident, NodeInfo node, bool canSkip)
  721. {
  722. node.Value = null;
  723. node.ValueType = ident;
  724. node.NodeType = XmlNodeType.Text;
  725. switch (ident) {
  726. case BF.Zero:
  727. node.TypedValue = 0;
  728. break;
  729. case BF.One:
  730. node.TypedValue = 1;
  731. break;
  732. case BF.BoolFalse:
  733. node.TypedValue = false;
  734. break;
  735. case BF.BoolTrue:
  736. node.TypedValue = true;
  737. break;
  738. case BF.Int8:
  739. node.TypedValue = ReadByteOrError ();
  740. break;
  741. case BF.Int16:
  742. node.TypedValue = source.Reader.ReadInt16 ();
  743. break;
  744. case BF.Int32:
  745. node.TypedValue = source.Reader.ReadInt32 ();
  746. break;
  747. case BF.Int64:
  748. node.TypedValue = source.Reader.ReadInt64 ();
  749. break;
  750. case BF.Single:
  751. node.TypedValue = source.Reader.ReadSingle ();
  752. break;
  753. case BF.Double:
  754. node.TypedValue = source.Reader.ReadDouble ();
  755. break;
  756. case BF.Decimal:
  757. int [] bits = new int [4];
  758. bits [3] = source.Reader.ReadInt32 ();
  759. bits [2] = source.Reader.ReadInt32 ();
  760. bits [0] = source.Reader.ReadInt32 ();
  761. bits [1] = source.Reader.ReadInt32 ();
  762. node.TypedValue = new Decimal (bits);
  763. break;
  764. case BF.DateTime:
  765. node.TypedValue = new DateTime (source.Reader.ReadInt64 ());
  766. break;
  767. //case BF.UniqueId: // identical to .Text
  768. case BF.Base64:
  769. byte [] base64 = new byte [ReadVariantSize ()];
  770. source.Reader.Read (base64, 0, base64.Length);
  771. node.TypedValue = base64;
  772. break;
  773. case BF.Base64Fixed:
  774. base64 = new byte [source.Reader.ReadInt16 ()];
  775. source.Reader.Read (base64, 0, base64.Length);
  776. node.TypedValue = base64;
  777. break;
  778. case BF.TimeSpan:
  779. node.TypedValue = new TimeSpan (source.Reader.ReadInt64 ());
  780. break;
  781. case BF.UniqueIdFromGuid:
  782. byte [] guid = new byte [16];
  783. source.Reader.Read (guid, 0, guid.Length);
  784. node.TypedValue = new UniqueId (new Guid (guid));
  785. break;
  786. case BF.Guid:
  787. guid = new byte [16];
  788. source.Reader.Read (guid, 0, guid.Length);
  789. node.TypedValue = new Guid (guid);
  790. break;
  791. case BF.Text:
  792. node.Value = ReadUTF8 ();
  793. node.NodeType = XmlNodeType.Text;
  794. break;
  795. case BF.EmptyText:
  796. node.Value = String.Empty;
  797. node.NodeType = XmlNodeType.Text;
  798. break;
  799. default:
  800. if (!canSkip)
  801. throw new ArgumentException (String.Format ("Unexpected binary XML data at position {1}: {0:X}", ident + (is_next_end_element ? 1 : 0), source.Position));
  802. next = ident;
  803. return false;
  804. }
  805. return true;
  806. /*
  807. if (ident == 0x8B) {
  808. // empty text
  809. node.Value = String.Empty;
  810. node.NodeType = XmlNodeType.Text;
  811. }
  812. else if (0x83 <= ident && ident <= 0x85 ||
  813. 0x9D <= ident && ident <= 0x9F) {
  814. // text
  815. int sizeSpec = ident > 0x90 ? ident - 0x9D : ident - 0x83;
  816. node.Value = ReadUTF8 (sizeSpec);
  817. node.NodeType = XmlNodeType.Text;
  818. is_next_end_element = ident > 0x90;
  819. }
  820. else {
  821. switch (ident) {
  822. case 0x7B: // byte
  823. case 0x7C: // short
  824. case 0x7D: // int
  825. case 0x7E: // long
  826. case 0x7F: // float
  827. case 0x80: // double
  828. case 0x81: // decimal
  829. case 0x82: // DateTime
  830. case 0x8D: // UniqueId
  831. case 0x8E: // TimeSpan
  832. case 0x8F: // Guid
  833. case 0xA0: // base64Binary
  834. Console.WriteLine ("At position {0}({0:X})", source.Position);
  835. throw new NotImplementedException ();
  836. default:
  837. if (!canSkip)
  838. throw new ArgumentException (String.Format ("Unexpected binary XML data at position {1}: {0:X}", ident, source.Position));
  839. next = ident;
  840. return false;
  841. }
  842. }
  843. return true;
  844. */
  845. }
  846. private int ReadVariantSize ()
  847. {
  848. int size = 0;
  849. // If sizeSpec < 0, then it is variant size specifier.
  850. // Otherwise it is fixed size s = sizeSpec + 1 byte(s).
  851. do {
  852. size <<= 7;
  853. byte got = ReadByteOrError ();
  854. size += got;
  855. if (got < 0x80)
  856. break;
  857. size -= 0x80;
  858. } while (true);
  859. return size;
  860. }
  861. private string ReadUTF8 ()
  862. {
  863. int size = ReadVariantSize ();
  864. if (size == 0)
  865. return String.Empty;
  866. if (tmp_buffer.Length < size) {
  867. int extlen = tmp_buffer.Length * 2;
  868. tmp_buffer = new byte [size < extlen ? extlen : size];
  869. }
  870. size = source.Read (tmp_buffer, 0, size);
  871. return utf8enc.GetString (tmp_buffer, 0, size);
  872. }
  873. private XmlDictionaryString ReadDictName ()
  874. {
  875. int key = ReadVariantSize ();
  876. XmlDictionaryString s;
  877. if ((key & 1) == 1) {
  878. if (session.TryLookup (key >> 1, out s))
  879. return s;
  880. } else {
  881. if (dictionary.TryLookup (key >> 1, out s))
  882. return s;
  883. }
  884. 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));
  885. }
  886. private byte ReadByteOrError ()
  887. {
  888. int ret = source.ReadByte ();
  889. if (ret < 0)
  890. throw new XmlException (String.Format ("Unexpected end of binary stream. Position is at {0}", source.Position));
  891. return (byte) ret;
  892. }
  893. public override void ResolveEntity ()
  894. {
  895. throw new NotSupportedException ("this XmlReader does not support ResolveEntity.");
  896. }
  897. public override bool TryGetBase64ContentLength (out int length)
  898. {
  899. length = 0;
  900. if (current.ValueType != BF.Base64 &&
  901. current.ValueType != BF.Base64Fixed)
  902. return false;
  903. length = ((byte []) current.TypedValue).Length;
  904. return true;
  905. }
  906. public override string ReadContentAsString ()
  907. {
  908. string value = Value;
  909. do {
  910. switch (NodeType) {
  911. case XmlNodeType.Element:
  912. case XmlNodeType.EndElement:
  913. return value;
  914. case XmlNodeType.Text:
  915. value += Value;
  916. break;
  917. }
  918. } while (Read ());
  919. return value;
  920. }
  921. #region read typed content
  922. public override int ReadContentAsInt ()
  923. {
  924. int ret = GetIntValue ();
  925. Read ();
  926. return ret;
  927. }
  928. int GetIntValue ()
  929. {
  930. switch (node.ValueType) {
  931. case BF.Zero:
  932. return 0;
  933. case BF.One:
  934. return 1;
  935. case BF.Int8:
  936. return (byte) current.TypedValue;
  937. case BF.Int16:
  938. return (short) current.TypedValue;
  939. case BF.Int32:
  940. return (int) current.TypedValue;
  941. }
  942. throw new InvalidOperationException ("Current content is not an integer");
  943. }
  944. public override long ReadContentAsLong ()
  945. {
  946. if (node.ValueType == BF.Int64) {
  947. long v = (long) current.TypedValue;
  948. Read ();
  949. return v;
  950. }
  951. return ReadContentAsInt ();
  952. }
  953. public override float ReadContentAsFloat ()
  954. {
  955. if (node.ValueType != BF.Single)
  956. throw new InvalidOperationException ("Current content is not a single");
  957. float v = (float) current.TypedValue;
  958. Read ();
  959. return v;
  960. }
  961. public override double ReadContentAsDouble ()
  962. {
  963. if (node.ValueType != BF.Double)
  964. throw new InvalidOperationException ("Current content is not a double");
  965. double v = (double) current.TypedValue;
  966. Read ();
  967. return v;
  968. }
  969. // FIXME: this is not likely to consume sequential base64 nodes.
  970. public override byte [] ReadContentAsBase64 ()
  971. {
  972. byte [] ret = null;
  973. if (node.ValueType != BF.Base64 &&
  974. node.ValueType != BF.Base64Fixed)
  975. throw new InvalidOperationException ("Current content is not base64");
  976. while (NodeType == XmlNodeType.Text &&
  977. (node.ValueType == BF.Base64 || node.ValueType == BF.Base64Fixed)) {
  978. if (ret == null)
  979. ret = (byte []) node.TypedValue;
  980. else {
  981. byte [] tmp = (byte []) node.TypedValue;
  982. byte [] tmp2 = new byte [ret.Length + tmp.Length];
  983. Array.Copy (ret, tmp2, ret.Length);
  984. Array.Copy (tmp, 0, tmp2, ret.Length, tmp.Length);
  985. ret = tmp2;
  986. }
  987. Read ();
  988. //MoveToContent ();
  989. }
  990. return ret;
  991. }
  992. public override Guid ReadContentAsGuid ()
  993. {
  994. if (node.ValueType != BF.Guid)
  995. throw new InvalidOperationException ("Current content is not a Guid");
  996. Guid ret = (Guid) node.TypedValue;
  997. Read ();
  998. return ret;
  999. }
  1000. public override UniqueId ReadContentAsUniqueId ()
  1001. {
  1002. switch (node.ValueType) {
  1003. case BF.Text:
  1004. UniqueId ret = new UniqueId (node.Value);
  1005. Read ();
  1006. return ret;
  1007. case BF.UniqueIdFromGuid:
  1008. ret = (UniqueId) node.TypedValue;
  1009. Read ();
  1010. return ret;
  1011. default:
  1012. throw new InvalidOperationException ("Current content is not a UniqueId");
  1013. }
  1014. }
  1015. #endregion
  1016. }
  1017. }