PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Otp/OtpInputStream.cs

https://github.com/saleyn/otp.net
C# | 998 lines | 567 code | 124 blank | 307 comment | 82 complexity | e8e6af8d97d26b1cb759dd8cb280cae8 MD5 | raw file
  1. /*``The contents of this file are subject to the Erlang Public License,
  2. * Version 1.1, (the "License"); you may not use this file except in
  3. * compliance with the License. You should have received a copy of the
  4. * Erlang Public License along with this software. If not, it can be
  5. * retrieved via the world wide web at http://www.erlang.org/.
  6. *
  7. * Software distributed under the License is distributed on an "AS IS"
  8. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9. * the License for the specific language governing rights and limitations
  10. * under the License.
  11. *
  12. * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
  13. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  14. * AB. All Rights Reserved.''
  15. *
  16. * Converted from Java to C# by Vlad Dumitrescu (vlad_Dumitrescu@hotmail.com)
  17. */
  18. namespace Otp
  19. {
  20. using System;
  21. /*
  22. * Provides a stream for decoding Erlang terms from external format.
  23. *
  24. * <p> Note that this class is not synchronized, if you need
  25. * synchronization you must provide it yourself.
  26. **/
  27. public class OtpInputStream : System.IO.MemoryStream
  28. {
  29. byte[] m_buf2;
  30. byte[] m_buf4;
  31. byte[] m_buf8;
  32. private int m_Origin;
  33. /*
  34. * Create a stream from a buffer containing encoded Erlang terms.
  35. **/
  36. public OtpInputStream(byte[] buf)
  37. : this(buf, 0, buf.Length)
  38. {
  39. }
  40. /*
  41. * Create a stream from a buffer containing encoded
  42. * Erlang terms at the given offset and length.
  43. **/
  44. public OtpInputStream(byte[] buf, int offset, int length)
  45. : base(buf, offset, length, false, true)
  46. {
  47. m_buf2 = new byte[2];
  48. m_buf4 = new byte[4];
  49. m_buf8 = new byte[8];
  50. m_Origin = offset;
  51. }
  52. public int BufferPosition
  53. {
  54. get { return m_Origin + (int)Position; }
  55. }
  56. ///*
  57. //* Get the current position in the stream.
  58. //*
  59. //* @return the current position in the stream.
  60. //**/
  61. //public int getPos()
  62. //{
  63. // return (int) base.Position;
  64. //}
  65. ///*
  66. //* Set the current position in the stream.
  67. //*
  68. //* @param pos the position to move to in the stream. If pos
  69. //* indicates a position beyond the end of the stream, the position
  70. //* is move to the end of the stream instead. If pos is negative, the
  71. //* position is moved to the beginning of the stream instead.
  72. //*
  73. //* @return the previous position in the stream.
  74. //**/
  75. //public int setPos(int pos)
  76. //{
  77. // int oldpos = (int) base.Position;
  78. // if (pos > (int) base.Length)
  79. // pos = (int) base.Length;
  80. // else if (pos < 0)
  81. // pos = 0;
  82. // base.Position = (System.Int64) pos;
  83. // return oldpos;
  84. //}
  85. /*
  86. * Read an array of bytes from the stream. The method reads at most
  87. * buf.length bytes from the input stream.
  88. *
  89. * @return the number of bytes read.
  90. *
  91. * @exception OtpErlangDecodeException if the next byte cannot be
  92. * read.
  93. **/
  94. public int readN(byte[] buf)
  95. {
  96. try
  97. {
  98. return base.Read(buf, 0, buf.Length);
  99. }
  100. catch (System.IO.IOException)
  101. {
  102. throw new Erlang.Exception("Cannot read from input stream");
  103. }
  104. }
  105. /*
  106. * Look ahead one position in the stream without consuming the byte
  107. * found there.
  108. *
  109. * @return the next byte in the stream, as an integer.
  110. *
  111. * @exception Erlang.DecodeException if the next byte cannot be
  112. * read.
  113. **/
  114. public int peek()
  115. {
  116. int i;
  117. try
  118. {
  119. i = base.ReadByte();
  120. base.Seek(-1, System.IO.SeekOrigin.Current);
  121. if (i < 0)
  122. i += 256;
  123. return i;
  124. }
  125. catch (System.Exception)
  126. {
  127. throw new Erlang.Exception("Cannot read from input stream");
  128. }
  129. }
  130. /*
  131. * Read a one byte integer from the stream.
  132. *
  133. * @return the byte read, as an integer.
  134. *
  135. * @exception Erlang.DecodeException if the next byte cannot be
  136. * read.
  137. **/
  138. public int read1()
  139. {
  140. int i;
  141. i = base.ReadByte();
  142. if (i < 0)
  143. {
  144. throw new Erlang.Exception("Cannot read from input stream");
  145. }
  146. return i;
  147. }
  148. /*
  149. * Read a two byte big endian integer from the stream.
  150. *
  151. * @return the bytes read, converted from big endian to an integer.
  152. *
  153. * @exception Erlang.DecodeException if the next byte cannot be
  154. * read.
  155. **/
  156. public int read2BE()
  157. {
  158. try
  159. {
  160. base.Read(m_buf2, 0, m_buf2.Length);
  161. }
  162. catch (System.IO.IOException)
  163. {
  164. throw new Erlang.Exception("Cannot read from input stream");
  165. }
  166. return ((((int)m_buf2[0] << 8) & 0xff00) + (((int)m_buf2[1]) & 0xff));
  167. }
  168. /*
  169. * Read a four byte big endian integer from the stream.
  170. *
  171. * @return the bytes read, converted from big endian to an integer.
  172. *
  173. * @exception Erlang.DecodeException if the next byte cannot be
  174. * read.
  175. **/
  176. public int read4BE()
  177. {
  178. try
  179. {
  180. base.Read(m_buf4, 0, m_buf4.Length);
  181. }
  182. catch (System.IO.IOException)
  183. {
  184. throw new Erlang.Exception("Cannot read from input stream");
  185. }
  186. return read4BE(m_buf4);
  187. }
  188. public static int read4BE(byte[] b)
  189. {
  190. System.Diagnostics.Debug.Assert(b.Length == 4);
  191. return (int)((((int)b[0] << 24) & 0xff000000) + (((int)b[1] << 16) & 0xff0000) + (((int)b[2] << 8) & 0xff00) + (((int)b[3]) & 0xff));
  192. }
  193. /*
  194. * Read an eight byte big endian integer from the stream.
  195. *
  196. * @return the bytes read, converted from big endian to an integer.
  197. *
  198. * @exception Erlang.DecodeException if the next byte cannot be
  199. * read.
  200. **/
  201. public System.UInt64 read8BE()
  202. {
  203. try
  204. {
  205. base.Read(m_buf8, 0, m_buf8.Length);
  206. }
  207. catch (System.IO.IOException)
  208. {
  209. throw new Erlang.Exception("Cannot read from input stream");
  210. }
  211. System.UInt64 i1 = (System.UInt64)((((int)m_buf8[0] << 24) & 0xff000000)
  212. + (((int)m_buf8[1] << 16) & 0xff0000)
  213. + (((int)m_buf8[2] << 8) & 0xff00)
  214. + (((int)m_buf8[3]) & 0xff));
  215. System.UInt64 i2 = (i1 << 32) & 0xffffffff00000000
  216. + (System.UInt64)((((int)m_buf8[4] << 24) & 0xff000000)
  217. + (((int)m_buf8[5] << 16) & 0xff0000)
  218. + (((int)m_buf8[6] << 8) & 0xff00)
  219. + (((int)m_buf8[7]) & 0xff));
  220. return i2;
  221. }
  222. /*
  223. * Read a two byte little endian integer from the stream.
  224. *
  225. * @return the bytes read, converted from little endian to an
  226. * integer.
  227. *
  228. * @exception Erlang.DecodeException if the next byte cannot be
  229. * read.
  230. **/
  231. public int read2LE()
  232. {
  233. try
  234. {
  235. base.Read(m_buf2, 0, m_buf2.Length);
  236. }
  237. catch (System.IO.IOException)
  238. {
  239. throw new Erlang.Exception("Cannot read from input stream");
  240. }
  241. return ((((int)m_buf2[1] << 8) & 0xff00) + (((int)m_buf2[0]) & 0xff));
  242. }
  243. /*
  244. * Read a four byte little endian integer from the stream.
  245. *
  246. * @return the bytes read, converted from little endian to an
  247. * integer.
  248. *
  249. * @exception Erlang.DecodeException if the next byte cannot be
  250. * read.
  251. **/
  252. public int read4LE()
  253. {
  254. try
  255. {
  256. base.Read(m_buf4, 0, m_buf4.Length);
  257. }
  258. catch (System.IO.IOException)
  259. {
  260. throw new Erlang.Exception("Cannot read from input stream");
  261. }
  262. return (int)((((int)m_buf4[3] << 24) & 0xff000000) + (((int)m_buf4[2] << 16) & 0xff0000)
  263. + (((int)m_buf4[1] << 8) & 0xff00) + (((int)m_buf4[0]) & 0xff));
  264. }
  265. /*
  266. * Read an Erlang atom from the stream and interpret the value as a
  267. * boolean.
  268. *
  269. * @return true if the atom at the current position in the stream
  270. * contains the value 'true' (ignoring case), false otherwise.
  271. *
  272. * @exception Erlang.DecodeException if the next term in the
  273. * stream is not an atom.
  274. **/
  275. public bool read_boolean()
  276. {
  277. return System.Boolean.Parse(this.read_atom());
  278. }
  279. /*
  280. * Read an Erlang atom from the stream.
  281. *
  282. * @return a String containing the value of the atom.
  283. *
  284. * @exception Erlang.DecodeException if the next term in the
  285. * stream is not an atom.
  286. **/
  287. public string read_atom()
  288. {
  289. int tag = this.read1();
  290. if (tag == OtpExternal.versionTag)
  291. {
  292. tag = this.read1();
  293. }
  294. if (tag != OtpExternal.atomTag)
  295. {
  296. throw new Erlang.Exception("wrong tag encountered, expected " + OtpExternal.atomTag + ", got " + tag);
  297. }
  298. int len = this.read2BE();
  299. int n = len > OtpExternal.maxAtomLength ? OtpExternal.maxAtomLength : len;
  300. string s = System.Text.Encoding.ASCII.GetString(base.GetBuffer(), BufferPosition, len);
  301. base.Position += len;
  302. if (n != len)
  303. s = s.Substring(0, n);
  304. return s;
  305. }
  306. /*
  307. * Read an Erlang binary from the stream.
  308. *
  309. * @return a byte array containing the value of the binary.
  310. *
  311. * @exception Erlang.DecodeException if the next term in the
  312. * stream is not a binary.
  313. **/
  314. public byte[] read_binary()
  315. {
  316. int tag;
  317. int len;
  318. byte[] bin;
  319. tag = this.read1();
  320. if (tag == OtpExternal.versionTag)
  321. {
  322. tag = this.read1();
  323. }
  324. if (tag != OtpExternal.binTag)
  325. {
  326. throw new Erlang.Exception("Wrong tag encountered, expected " + OtpExternal.binTag + ", got " + tag);
  327. }
  328. len = this.read4BE();
  329. bin = new byte[len];
  330. this.readN(bin);
  331. return bin;
  332. }
  333. /*
  334. * Read an Erlang float from the stream.
  335. *
  336. * @return the float value.
  337. *
  338. * @exception Erlang.DecodeException if the next term in the
  339. * stream is not a float.
  340. **/
  341. public float read_float()
  342. {
  343. double d = this.read_double();
  344. float f = (float)d;
  345. if (System.Math.Abs(d - f) >= 1.0E-20)
  346. throw new Erlang.Exception("Value cannot be represented as float: " + d);
  347. return f;
  348. }
  349. /*
  350. * Read an Erlang float from the stream.
  351. *
  352. * @return the float value, as a double.
  353. *
  354. * @exception Erlang.DecodeException if the next term in the
  355. * stream is not a float.
  356. *
  357. **/
  358. public double read_double()
  359. {
  360. return getFloatOrDouble();
  361. }
  362. private double getFloatOrDouble()
  363. {
  364. // parse the stream
  365. int tag = this.read1();
  366. if (tag == OtpExternal.versionTag)
  367. {
  368. tag = this.read1();
  369. }
  370. byte[] strbuf;
  371. double parsedValue = 0.0;
  372. if (tag == OtpExternal.floatTag)
  373. {
  374. // get the string
  375. strbuf = new byte[31];
  376. this.readN(strbuf);
  377. char[] tmpChar = new char[strbuf.Length];
  378. strbuf.CopyTo(tmpChar, 0);
  379. System.String str = new System.String(tmpChar);
  380. //System.Diagnostics.Debug.WriteLine("getFloatOrDouble: str = " + str);
  381. try
  382. {
  383. // Easier than the java version.
  384. parsedValue = System.Double.Parse(str);
  385. return parsedValue;
  386. }
  387. catch
  388. {
  389. throw new Erlang.Exception("Error parsing float format: '" + str + "'");
  390. }
  391. }
  392. else if (tag == OtpExternal.newFloatTag)
  393. {
  394. this.readN(m_buf8);
  395. // IEEE 754 decoder
  396. if (BitConverter.IsLittleEndian)
  397. {
  398. Array.Reverse(m_buf8);
  399. }
  400. return BitConverter.ToDouble(m_buf8, 0);
  401. }
  402. else
  403. {
  404. throw new Erlang.Exception("Wrong tag encountered, expected " + OtpExternal.floatTag + ", got " + tag);
  405. }
  406. }
  407. /*
  408. * Read one byte from the stream.
  409. *
  410. * @return the byte read.
  411. *
  412. * @exception Erlang.DecodeException if the next byte cannot be
  413. * read.
  414. **/
  415. public byte read_byte()
  416. {
  417. long l = this.read_long();
  418. byte i = (byte)l;
  419. if (l != i)
  420. {
  421. throw new Erlang.Exception("Value too large for byte: " + l);
  422. }
  423. return i;
  424. }
  425. /*
  426. * Read a character from the stream.
  427. *
  428. * @return the character value.
  429. *
  430. * @exception Erlang.DecodeException if the next term in the
  431. * stream is not an integer that can be represented as a char.
  432. **/
  433. public char read_char()
  434. {
  435. long l = this.read_long();
  436. char i = (char)l;
  437. if (l != i)
  438. {
  439. throw new Erlang.Exception("Value too large for byte: " + l);
  440. }
  441. return i;
  442. }
  443. /*
  444. * Read an unsigned integer from the stream.
  445. *
  446. * @return the integer value.
  447. *
  448. * @exception Erlang.DecodeException if the next term in the
  449. * stream can not be represented as a positive integer.
  450. **/
  451. public int read_uint()
  452. {
  453. long l = this.read_long();
  454. int i = (int)l;
  455. if (l != i)
  456. {
  457. throw new Erlang.Exception("Value too large for integer: " + l);
  458. }
  459. else if (l < 0)
  460. {
  461. throw new Erlang.Exception("Value not unsigned: " + l);
  462. }
  463. return i;
  464. }
  465. /*
  466. * Read an integer from the stream.
  467. *
  468. * @return the integer value.
  469. *
  470. * @exception Erlang.DecodeException if the next term in the
  471. * stream can not be represented as an integer.
  472. **/
  473. public int read_int()
  474. {
  475. long l = this.read_long();
  476. int i = (int)l;
  477. if (l != i)
  478. {
  479. throw new Erlang.Exception("Value too large for byte: " + l);
  480. }
  481. return i;
  482. }
  483. /*
  484. * Read an unsigned short from the stream.
  485. *
  486. * @return the short value.
  487. *
  488. * @exception Erlang.DecodeException if the next term in the
  489. * stream can not be represented as a positive short.
  490. **/
  491. public short read_ushort()
  492. {
  493. long l = this.read_long();
  494. short i = (short)l;
  495. if (l != i)
  496. {
  497. throw new Erlang.Exception("Value too large for byte: " + l);
  498. }
  499. else if (l < 0)
  500. {
  501. throw new Erlang.Exception("Value not unsigned: " + l);
  502. }
  503. return i;
  504. }
  505. /*
  506. * Read a short from the stream.
  507. *
  508. * @return the short value.
  509. *
  510. * @exception Erlang.DecodeException if the next term in the
  511. * stream can not be represented as a short.
  512. **/
  513. public short read_short()
  514. {
  515. long l = this.read_long();
  516. short i = (short)l;
  517. if (l != i)
  518. {
  519. throw new Erlang.Exception("Value too large for byte: " + l);
  520. }
  521. return i;
  522. }
  523. /*
  524. * Read an unsigned long from the stream.
  525. *
  526. * @return the long value.
  527. *
  528. * @exception Erlang.DecodeException if the next term in the
  529. * stream can not be represented as a positive long.
  530. **/
  531. public ulong read_ulong()
  532. {
  533. return (ulong)read_long(false);
  534. }
  535. /*
  536. * Read a long from the stream.
  537. *
  538. * @return the long value.
  539. *
  540. * @exception Erlang.DecodeException if the next term in the
  541. * stream can not be represented as a long.
  542. **/
  543. public long read_long() { return read_long(true); }
  544. private long read_long(bool signed)
  545. {
  546. int tag;
  547. int sign;
  548. int arity;
  549. long val;
  550. tag = this.read1();
  551. if (tag == OtpExternal.versionTag)
  552. {
  553. tag = this.read1();
  554. }
  555. switch (tag)
  556. {
  557. case OtpExternal.smallIntTag:
  558. val = this.read1();
  559. break;
  560. case OtpExternal.intTag:
  561. val = this.read4BE();
  562. break;
  563. case OtpExternal.smallBigTag:
  564. {
  565. arity = this.read1();
  566. sign = this.read1();
  567. byte[] nb = new byte[arity];
  568. if (arity != this.readN(nb))
  569. {
  570. throw new Erlang.Exception("Cannot read from input stream. Expected smallBigTag arity " + arity);
  571. }
  572. if (arity > 8)
  573. throw new Erlang.Exception("Value too large for long type (arity=" + arity + ")");
  574. val = 0;
  575. for (int i = 0; i < arity; i++)
  576. {
  577. val |= (long)nb[i] << (i * 8);
  578. }
  579. val = (sign == 0 ? val : -val); // should deal with overflow
  580. if (sign == 1 && !signed)
  581. throw new Erlang.Exception("Requested unsigned, but read signed long value: " + val.ToString());
  582. break;
  583. }
  584. case OtpExternal.largeBigTag:
  585. default:
  586. throw new Erlang.Exception("Not valid integer tag: " + tag);
  587. }
  588. return val;
  589. }
  590. /*
  591. * Read a list header from the stream.
  592. *
  593. * @return the arity of the list.
  594. *
  595. * @exception Erlang.DecodeException if the next term in the
  596. * stream is not a list.
  597. **/
  598. public int read_list_head()
  599. {
  600. int arity = 0;
  601. int tag = this.read1();
  602. if (tag == OtpExternal.versionTag)
  603. {
  604. tag = this.read1();
  605. }
  606. switch (tag)
  607. {
  608. case OtpExternal.nilTag:
  609. arity = 0;
  610. break;
  611. case OtpExternal.stringTag:
  612. arity = this.read2BE();
  613. break;
  614. case OtpExternal.listTag:
  615. arity = this.read4BE();
  616. break;
  617. default:
  618. throw new Erlang.Exception("Not valid list tag: " + tag);
  619. }
  620. return arity;
  621. }
  622. /*
  623. * Read a tuple header from the stream.
  624. *
  625. * @return the arity of the tuple.
  626. *
  627. * @exception Erlang.DecodeException if the next term in the
  628. * stream is not a tuple.
  629. **/
  630. public int read_tuple_head()
  631. {
  632. int arity = 0;
  633. int tag = this.read1();
  634. if (tag == OtpExternal.versionTag)
  635. {
  636. tag = this.read1();
  637. }
  638. // decode the tuple header and get arity
  639. switch (tag)
  640. {
  641. case OtpExternal.smallTupleTag:
  642. arity = this.read1();
  643. break;
  644. case OtpExternal.largeTupleTag:
  645. arity = this.read4BE();
  646. break;
  647. default:
  648. throw new Erlang.Exception("Not valid tuple tag: " + tag);
  649. }
  650. return arity;
  651. }
  652. /*
  653. * Read an empty list from the stream.
  654. *
  655. * @return zero (the arity of the list).
  656. *
  657. * @exception Erlang.DecodeException if the next term in the
  658. * stream is not an empty list.
  659. **/
  660. public int read_nil()
  661. {
  662. int arity = 0;
  663. int tag = this.read1();
  664. if (tag == OtpExternal.versionTag)
  665. {
  666. tag = this.read1();
  667. }
  668. switch (tag)
  669. {
  670. case OtpExternal.nilTag:
  671. arity = 0;
  672. break;
  673. default:
  674. throw new Erlang.Exception("Not valid nil tag: " + tag);
  675. }
  676. return arity;
  677. }
  678. /*
  679. * Read an Erlang PID from the stream.
  680. *
  681. * @return the value of the PID.
  682. *
  683. * @exception Erlang.DecodeException if the next term in the
  684. * stream is not an Erlang PID.
  685. **/
  686. public Erlang.Pid read_pid()
  687. {
  688. System.String node;
  689. int id;
  690. int serial;
  691. int creation;
  692. int tag;
  693. tag = this.read1();
  694. if (tag == OtpExternal.versionTag)
  695. {
  696. tag = this.read1();
  697. }
  698. if (tag != OtpExternal.pidTag)
  699. {
  700. throw new Erlang.Exception("Wrong tag encountered, expected " + OtpExternal.pidTag + ", got " + tag);
  701. }
  702. node = this.read_atom();
  703. id = this.read4BE() & 0x7fff; // 15 bits
  704. serial = this.read4BE() & 0x07; // 3 bits
  705. creation = this.read1() & 0x03; // 2 bits
  706. return new Erlang.Pid(node, id, serial, creation);
  707. }
  708. /*
  709. * Read an Erlang port from the stream.
  710. *
  711. * @return the value of the port.
  712. *
  713. * @exception DecodeException if the next term in the
  714. * stream is not an Erlang port.
  715. **/
  716. public Erlang.Port read_port()
  717. {
  718. System.String node;
  719. int id;
  720. int creation;
  721. int tag;
  722. tag = this.read1();
  723. if (tag == OtpExternal.versionTag)
  724. {
  725. tag = this.read1();
  726. }
  727. if (tag != OtpExternal.portTag)
  728. {
  729. throw new Erlang.Exception("Wrong tag encountered, expected " + OtpExternal.portTag + ", got " + tag);
  730. }
  731. node = this.read_atom();
  732. id = this.read4BE() & 0x3ffff; // 18 bits
  733. creation = this.read1() & 0x03; // 2 bits
  734. return new Erlang.Port(node, id, creation);
  735. }
  736. /*
  737. * Read an Erlang reference from the stream.
  738. *
  739. * @return the value of the reference
  740. *
  741. * @exception DecodeException if the next term in the
  742. * stream is not an Erlang reference.
  743. **/
  744. public Erlang.Ref read_ref()
  745. {
  746. System.String node;
  747. int id;
  748. int creation;
  749. int tag;
  750. tag = this.read1();
  751. if (tag == OtpExternal.versionTag)
  752. {
  753. tag = this.read1();
  754. }
  755. switch (tag)
  756. {
  757. case OtpExternal.refTag:
  758. node = this.read_atom();
  759. id = this.read4BE() & 0x3ffff; // 18 bits
  760. creation = this.read1() & 0x03; // 2 bits
  761. return new Erlang.Ref(node, id, creation);
  762. case OtpExternal.newRefTag:
  763. int arity = this.read2BE();
  764. node = this.read_atom();
  765. creation = this.read1() & 0x03; // 2 bits
  766. int[] ids = new int[arity];
  767. for (int i = 0; i < arity; i++)
  768. {
  769. ids[i] = this.read4BE();
  770. }
  771. ids[0] &= 0x3ffff; // first id gets truncated to 18 bits
  772. return new Erlang.Ref(node, ids, creation);
  773. default:
  774. throw new Erlang.Exception("Wrong tag encountered, expected ref, got " + tag);
  775. }
  776. }
  777. /*
  778. * Read a string from the stream.
  779. *
  780. * @return the value of the string.
  781. *
  782. * @exception DecodeException if the next term in the
  783. * stream is not a string.
  784. **/
  785. public System.String read_string()
  786. {
  787. int tag;
  788. int len;
  789. char[] charbuf;
  790. tag = this.read1();
  791. if (tag == OtpExternal.versionTag)
  792. {
  793. tag = this.read1();
  794. }
  795. switch (tag)
  796. {
  797. case OtpExternal.stringTag:
  798. len = this.read2BE();
  799. string s = System.Text.Encoding.ASCII.GetString(base.GetBuffer(), BufferPosition, len);
  800. base.Position += len;
  801. return s;
  802. case OtpExternal.nilTag:
  803. return "";
  804. case OtpExternal.listTag:
  805. // List when unicode +
  806. len = this.read4BE();
  807. charbuf = new char[len];
  808. for (int i = 0; i < len; i++)
  809. charbuf[i] = this.read_char();
  810. this.read_nil();
  811. return new string(charbuf);
  812. default:
  813. throw new Erlang.Exception("Wrong tag encountered, expected " + OtpExternal.stringTag + " or " + OtpExternal.listTag + ", got " + tag);
  814. }
  815. }
  816. /*
  817. * Read an arbitrary Erlang term from the stream.
  818. *
  819. * @return the Erlang term.
  820. *
  821. * @exception DecodeException if the stream does not
  822. * contain a known Erlang type at the next position.
  823. **/
  824. public Erlang.Object read_any()
  825. {
  826. // calls one of the above functions, depending on o
  827. int tag = this.peek();
  828. if (tag == OtpExternal.versionTag)
  829. {
  830. this.read1();
  831. tag = this.peek();
  832. }
  833. //System.Diagnostics.Debug.WriteLine("read_any: tag = " + tag);
  834. switch (tag)
  835. {
  836. case OtpExternal.smallIntTag:
  837. case OtpExternal.intTag:
  838. case OtpExternal.smallBigTag:
  839. return new Erlang.Long(this);
  840. case OtpExternal.atomTag:
  841. string s = read_atom();
  842. if (s == "true")
  843. return new Erlang.Boolean(true);
  844. else if (s == "false")
  845. return new Erlang.Boolean(false);
  846. else
  847. return new Erlang.Atom(s);
  848. case OtpExternal.floatTag:
  849. case OtpExternal.newFloatTag:
  850. return new Erlang.Double(this);
  851. case OtpExternal.refTag:
  852. case OtpExternal.newRefTag:
  853. return new Erlang.Ref(this);
  854. case OtpExternal.portTag:
  855. return new Erlang.Port(this);
  856. case OtpExternal.pidTag:
  857. return new Erlang.Pid(this);
  858. case OtpExternal.stringTag:
  859. return new Erlang.String(this);
  860. case OtpExternal.listTag:
  861. case OtpExternal.nilTag:
  862. return new Erlang.List(this);
  863. case OtpExternal.smallTupleTag:
  864. case OtpExternal.largeTupleTag:
  865. return new Erlang.Tuple(this);
  866. case OtpExternal.binTag:
  867. return new Erlang.Binary(this);
  868. case OtpExternal.largeBigTag:
  869. default:
  870. throw new Erlang.Exception("Uknown data type: " + tag);
  871. }
  872. }
  873. }
  874. }