PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/otp.net/Otp/OtpInputStream.cs

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