PageRenderTime 59ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/NekoKun.Serialization.RubyMarshal/RubyMarshalWriter.cs

https://bitbucket.org/nekokun/nekokun
C# | 1035 lines | 446 code | 33 blank | 556 comment | 132 complexity | 4bcc03b7a60e5e20a1778d60f061b2c7 MD5 | raw file
Possible License(s): MIT, CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.IO;
  5. using System.Text.RegularExpressions;
  6. namespace NekoKun.Serialization.RubyMarshal
  7. {
  8. class RubyMarshalWriter
  9. {
  10. private Stream m_stream;
  11. private BinaryWriter m_writer;
  12. private Dictionary<object, int> m_objects;
  13. private Dictionary<RubySymbol, int> m_symbols;
  14. private Dictionary<object, object> m_compat_tbl;
  15. public RubyMarshalWriter(Stream output)
  16. {
  17. if (output == null)
  18. {
  19. throw new ArgumentNullException("output");
  20. }
  21. if (!output.CanWrite)
  22. {
  23. throw new ArgumentException("stream cannot write");
  24. }
  25. this.m_stream = output;
  26. this.m_objects = new Dictionary<object, int>();
  27. this.m_symbols = new Dictionary<RubySymbol, int>();
  28. this.m_compat_tbl = new Dictionary<object, object>();
  29. this.m_writer = new BinaryWriter(m_stream);
  30. }
  31. /// <summary>
  32. /// static void w_nbyte(const char *s, long n, struct dump_arg *arg)
  33. /// </summary>
  34. /// <param name="s"></param>
  35. /// <param name="n"></param>
  36. public void WriteNByte(byte[] s, int n)
  37. {
  38. this.m_writer.Write(s, 0, n);
  39. }
  40. /// <summary>
  41. /// static void w_byte(char c, struct dump_arg *arg)
  42. /// </summary>
  43. /// <param name="c"></param>
  44. public void WriteByte(byte c)
  45. {
  46. this.m_writer.Write(c);
  47. }
  48. /// <summary>
  49. /// static void w_long(long x, struct dump_arg *arg)
  50. /// </summary>
  51. /// <param name="value"></param>
  52. public void WriteLong(int value)
  53. {
  54. if (value == 0)
  55. {
  56. this.m_writer.Write((byte)0);
  57. }
  58. else if ((value > 0) && (value < 0x7b))
  59. {
  60. this.m_writer.Write((byte)(value + 5));
  61. }
  62. else if ((value < 0) && (value > -124))
  63. {
  64. this.m_writer.Write((sbyte)(value - 5));
  65. }
  66. else
  67. {
  68. sbyte num2;
  69. byte[] buffer = new byte[5];
  70. buffer[1] = (byte)(value & 0xff);
  71. buffer[2] = (byte)((value >> 8) & 0xff);
  72. buffer[3] = (byte)((value >> 0x10) & 0xff);
  73. buffer[4] = (byte)((value >> 0x18) & 0xff);
  74. int index = 4;
  75. if (value >= 0)
  76. {
  77. while (buffer[index] == 0)
  78. {
  79. index--;
  80. }
  81. num2 = (sbyte)index;
  82. }
  83. else
  84. {
  85. while (buffer[index] == 0xff)
  86. {
  87. index--;
  88. }
  89. num2 = (sbyte)-index;
  90. }
  91. buffer[0] = (byte)num2;
  92. this.m_writer.Write(buffer, 0, index + 1);
  93. }
  94. }
  95. /// <summary>
  96. /// static void w_bytes(const char *s, long n, struct dump_arg *arg)
  97. /// </summary>
  98. /// <param name="s"></param>
  99. /// <param name="n"></param>
  100. public void WriteBytes(byte[] s, int n)
  101. {
  102. WriteLong(n);
  103. WriteNByte(s, n);
  104. }
  105. public void WriteBytes(byte[] s)
  106. {
  107. WriteBytes(s, s.Length);
  108. }
  109. /// <summary>
  110. /// #define w_cstr(s, arg) w_bytes((s), strlen(s), (arg))
  111. /// </summary>
  112. /// <param name="s"></param>
  113. public void WriteCString(string s)
  114. {
  115. WriteLong(s.Length);
  116. this.m_writer.Write(Encoding.Default.GetBytes(s));
  117. }
  118. /// <summary>
  119. /// static void w_float(double d, struct dump_arg *arg)
  120. /// </summary>
  121. /// <param name="value"></param>
  122. public void WriteFloat(double value)
  123. {
  124. if (double.IsInfinity(value))
  125. {
  126. if (double.IsPositiveInfinity(value))
  127. {
  128. WriteCString("inf");
  129. }
  130. else
  131. {
  132. WriteCString("-inf");
  133. }
  134. }
  135. else if (double.IsNaN(value))
  136. {
  137. WriteCString("nan");
  138. }
  139. else
  140. {
  141. WriteCString(string.Format("{0:g}", value));
  142. }
  143. }
  144. public void WriteFloat(float value)
  145. {
  146. WriteFloat((double)value);
  147. }
  148. public void WriteFloat(RubyFloat value)
  149. {
  150. WriteFloat(value.Value);
  151. }
  152. /// <summary>
  153. /// static void w_symbol(ID id, struct dump_arg *arg)
  154. /// </summary>
  155. /// <param name="id"></param>
  156. public void WriteSymbol(RubySymbol id)
  157. {
  158. string sym;
  159. int num;
  160. System.Text.Encoding encidx = null;
  161. if (this.m_symbols.TryGetValue(id, out num)) {
  162. WriteByte(RubyMarshal.Types.SymbolLink);
  163. WriteLong(num);
  164. }
  165. else {
  166. sym = id.Name;
  167. if (sym.Length == 0) {
  168. throw new InvalidDataException("can't dump anonymous ID");
  169. }
  170. encidx = id.Encoding;
  171. if (encidx == Encoding.ASCII || encidx == Encoding.Default || encidx == Encoding.UTF8) {
  172. encidx = null;
  173. }
  174. if (encidx != null) {
  175. WriteByte(RubyMarshal.Types.InstanceVariable);
  176. }
  177. WriteByte(RubyMarshal.Types.Symbol);
  178. WriteCString(sym);
  179. this.m_symbols.Add(id, this.m_symbols.Count);
  180. if (encidx != null) {
  181. WriteEncoding(id, 0);
  182. }
  183. }
  184. }
  185. /// <summary>
  186. /// static void w_unique(VALUE s, struct dump_arg *arg)
  187. /// </summary>
  188. /// <param name="s"></param>
  189. public void WriteUnique(RubySymbol s)
  190. {
  191. WriteSymbol(s);
  192. }
  193. /// <summary>
  194. /// static void w_extended(VALUE klass, struct dump_arg *arg, int check)
  195. /// </summary>
  196. /// <param name="klass"></param>
  197. /// <param name="check"></param>
  198. public void WriteExtended(object klass, bool check)
  199. {
  200. RubyObject fobj = klass as RubyObject;
  201. if (fobj != null)
  202. {
  203. foreach (RubyModule item in fobj.ExtendModules)
  204. {
  205. WriteByte(RubyMarshal.Types.Extended);
  206. WriteUnique(item.Symbol);
  207. }
  208. }
  209. }
  210. /// <summary>
  211. /// static void w_class(char type, VALUE obj, struct dump_arg *arg, int check)
  212. /// </summary>
  213. /// <param name="type"></param>
  214. /// <param name="obj"></param>
  215. /// <param name="check"></param>
  216. public void WriteClass(byte type, object obj, bool check)
  217. {
  218. object real_obj;
  219. if (this.m_compat_tbl.TryGetValue(obj, out real_obj))
  220. {
  221. obj = real_obj;
  222. }
  223. RubyObject fobj = obj as RubyObject;
  224. if (fobj != null)
  225. {
  226. RubyClass klass = RubyClass.GetClass(fobj.ClassName);
  227. WriteExtended(klass, check);
  228. WriteByte(type);
  229. WriteUnique(fobj.ClassName);
  230. }
  231. }
  232. /// <summary>
  233. /// static void w_uclass(VALUE obj, VALUE super, struct dump_arg *arg)
  234. /// </summary>
  235. /// <param name="obj"></param>
  236. /// <param name="super"></param>
  237. public void WriteUserClass(object obj, RubyClass super)
  238. {
  239. RubyObject fobj = obj as RubyObject;
  240. if (fobj != null)
  241. {
  242. RubyClass klass = fobj.Class;
  243. WriteExtended(klass, true);
  244. if (klass != super)
  245. {
  246. WriteByte(RubyMarshal.Types.UserClass);
  247. WriteUnique(klass.Symbol);
  248. }
  249. }
  250. else
  251. {
  252. throw new InvalidOperationException();
  253. }
  254. }
  255. /// <summary>
  256. /// static void w_encoding(VALUE obj, long num, struct dump_call_arg *arg)
  257. /// </summary>
  258. /// <param name="obj"></param>
  259. /// <param name="num"></param>
  260. public void WriteEncoding(object obj, int num)
  261. {
  262. Encoding encidx =null;
  263. if (obj is RubyObject)
  264. encidx = (obj as RubyObject).Encoding;
  265. if (encidx == null)
  266. {
  267. WriteLong(num);
  268. return;
  269. }
  270. WriteLong(num + 1);
  271. if (encidx == Encoding.Default)
  272. {
  273. /* special treatment for US-ASCII and UTF-8 */
  274. WriteSymbol(RubyMarshal.IDs.E);
  275. WriteObject(false);
  276. return;
  277. }
  278. else if (encidx == Encoding.UTF8) {
  279. WriteSymbol(RubyMarshal.IDs.E);
  280. WriteObject(true);
  281. return;
  282. }
  283. WriteSymbol(RubyMarshal.IDs.encoding);
  284. WriteObject(RubySymbol.GetSymbol(encidx.BodyName));
  285. }
  286. /// <summary>
  287. /// static void w_ivar(VALUE obj, st_table *tbl, struct dump_call_arg *arg)
  288. /// </summary>
  289. /// <param name="obj"></param>
  290. public void WriteInstanceVariable(RubyObject obj, Dictionary<RubySymbol, object> tbl)
  291. {
  292. int num = tbl != null ? tbl.Count : 0;
  293. WriteEncoding(obj, num);
  294. if (tbl != null) {
  295. foreach (KeyValuePair<RubySymbol, object> item in tbl)
  296. {
  297. if (item.Key == RubyMarshal.IDs.encoding) continue;
  298. if (item.Key == RubyMarshal.IDs.E) continue;
  299. WriteSymbol(item.Key);
  300. WriteObject(item.Value);
  301. }
  302. }
  303. }
  304. /// <summary>
  305. /// static void w_objivar(VALUE obj, struct dump_call_arg *arg)
  306. /// </summary>
  307. /// <param name="obj"></param>
  308. public void WriteObjectInstanceVariable(RubyObject obj)
  309. {
  310. WriteInstanceVariable(obj, obj.InstanceVariables);
  311. }
  312. /// <summary>
  313. /// static void w_object(VALUE obj, struct dump_arg *arg, int limit)
  314. /// </summary>
  315. /// <param name="obj"></param>
  316. public void WriteObject(object obj)
  317. {
  318. int num;
  319. if (this.m_objects.TryGetValue(obj, out num))
  320. {
  321. WriteByte(RubyMarshal.Types.Link);
  322. WriteLong(num);
  323. return;
  324. }
  325. if (obj == null || obj == RubyNil.Instance)
  326. {
  327. WriteByte(RubyMarshal.Types.Nil);
  328. }
  329. else if (obj is bool && (bool)obj == true)
  330. WriteByte(RubyMarshal.Types.True);
  331. else if (obj is bool && (bool)obj == false)
  332. WriteByte(RubyMarshal.Types.False);
  333. else if (obj is int) {
  334. int v = (int) obj;
  335. // (2**30).class => Bignum
  336. // (2**30-1).class => Fixnum
  337. // (-2**30-1).class=> Bignum
  338. // (-2**30).class => Fixnum
  339. if (v <= 1073741823 && v >= -1073741824)
  340. {
  341. WriteByte(RubyMarshal.Types.Fixnum);
  342. WriteLong(v);
  343. }
  344. else
  345. {
  346. WriteObject(RubyBignum.Create(v));
  347. }
  348. }
  349. else if (obj is RubySymbol) {
  350. WriteSymbol(obj as RubySymbol);
  351. }
  352. else {
  353. RubyObject fobj = obj as RubyObject;
  354. bool hasiv = false;
  355. if (fobj != null)
  356. hasiv = (obj as RubyObject).InstanceVariables.Count > 0 || fobj.Encoding != null;
  357. if (obj is IRubyUserdefinedMarshalDumpObject)
  358. {
  359. this.m_objects.Add(obj, this.m_objects.Count);
  360. object result = (obj as IRubyUserdefinedMarshalDumpObject).Dump();
  361. if (hasiv)
  362. WriteByte(RubyMarshal.Types.InstanceVariable);
  363. WriteClass(RubyMarshal.Types.UserMarshal, obj, false);
  364. WriteObject(result);
  365. if (hasiv)
  366. WriteObjectInstanceVariable(fobj);
  367. return;
  368. }
  369. if (obj is IRubyUserdefinedDumpObject)
  370. {
  371. byte[] result = (obj as IRubyUserdefinedDumpObject).Dump();
  372. if (hasiv)
  373. WriteByte(RubyMarshal.Types.InstanceVariable);
  374. WriteClass(RubyMarshal.Types.UserDefined, obj, false);
  375. WriteBytes(result, result.Length);
  376. if (hasiv)
  377. WriteObjectInstanceVariable(fobj);
  378. this.m_objects.Add(obj, this.m_objects.Count);
  379. return;
  380. }
  381. this.m_objects.Add(obj, this.m_objects.Count);
  382. /*
  383. {
  384. st_data_t compat_data;
  385. rb_alloc_func_t allocator = rb_get_alloc_func(RBASIC(obj)->klass);
  386. if (st_lookup(compat_allocator_tbl,
  387. (st_data_t)allocator,
  388. &compat_data)) {
  389. marshal_compat_t *compat = (marshal_compat_t*)compat_data;
  390. VALUE real_obj = obj;
  391. obj = compat->dumper(real_obj);
  392. st_insert(arg->compat_tbl, (st_data_t)obj, (st_data_t)real_obj);
  393. if (obj != real_obj && !ivtbl) hasiv = 0;
  394. }
  395. }*/
  396. if (hasiv)
  397. WriteByte(RubyMarshal.Types.InstanceVariable);
  398. if (obj is RubyClass)
  399. {
  400. WriteByte(RubyMarshal.Types.Class);
  401. WriteCString((obj as RubyClass).Name);
  402. }
  403. else if (obj is RubyModule)
  404. {
  405. WriteByte(RubyMarshal.Types.Module);
  406. WriteCString((obj as RubyModule).Name);
  407. }
  408. else if (obj is float)
  409. {
  410. WriteByte(RubyMarshal.Types.Float);
  411. WriteFloat((float)obj);
  412. }
  413. else if (obj is double)
  414. {
  415. WriteByte(RubyMarshal.Types.Float);
  416. WriteFloat((double)obj);
  417. }
  418. else if (obj is RubyFloat)
  419. {
  420. WriteByte(RubyMarshal.Types.Float);
  421. WriteFloat((RubyFloat)obj);
  422. }
  423. else if (obj is RubyBignum)
  424. {
  425. RubyBignum value = (RubyBignum) obj;
  426. char ch;
  427. if (value.Sign > 0)
  428. ch = '+';
  429. else if (value.Sign < 0)
  430. ch = '-';
  431. else
  432. ch = '0';
  433. this.m_writer.Write((byte)ch);
  434. uint[] words = value.GetWords();
  435. int num2 = words.Length * 2;
  436. int index = words.Length - 1;
  437. bool flag = false;
  438. if ((words.Length > 0) && ((words[index] >> 0x10) == 0))
  439. {
  440. num--;
  441. flag = true;
  442. }
  443. this.WriteLong(num2);
  444. for (int i = 0; i < words.Length; i++)
  445. {
  446. if (flag && (i == index))
  447. {
  448. this.m_writer.Write((ushort)words[i]);
  449. }
  450. else
  451. {
  452. this.m_writer.Write(words[i]);
  453. }
  454. }
  455. }
  456. else if (obj is RubyString || obj is string)
  457. {
  458. RubyString v;
  459. if (obj is string)
  460. v = new RubyString(obj as string);
  461. else
  462. v = (RubyString)obj;
  463. WriteUserClass(v, RubyClass.GetClass("String"));
  464. WriteByte(RubyMarshal.Types.String);
  465. WriteBytes(v.Raw);
  466. }
  467. else if (obj is RubyRegexp)
  468. {
  469. RubyRegexp v = (RubyRegexp) obj;
  470. WriteUserClass(obj, RubyClass.GetClass("Regexp"));
  471. WriteByte(RubyMarshal.Types.Regexp);
  472. WriteBytes(v.Pattern.Raw);
  473. WriteByte((byte)v.Options);
  474. }
  475. else if (obj is RubyArray || obj is List<object>)
  476. {
  477. RubyArray v;
  478. if (obj is List<object>)
  479. v = new RubyArray(obj as List<object>);
  480. else
  481. v = (RubyArray)obj;
  482. WriteUserClass(v, RubyClass.GetClass("Array"));
  483. WriteByte(RubyMarshal.Types.Array);
  484. WriteLong(v.Length);
  485. for (int i = 0; i < v.Count; i++)
  486. WriteObject(v[i]);
  487. }
  488. else if (obj is RubyHash)
  489. {
  490. RubyHash v = (RubyHash) obj;
  491. WriteUserClass(obj, RubyClass.GetClass("Hash"));
  492. WriteByte(v.DefaultValue != null ? RubyMarshal.Types.HashWithDefault : RubyMarshal.Types.Hash);
  493. WriteLong(v.Length);
  494. foreach (KeyValuePair<object, object> item in v)
  495. {
  496. WriteObject(item.Key);
  497. WriteObject(item.Value);
  498. }
  499. if (v.DefaultValue != null) WriteObject(v.DefaultValue);
  500. }
  501. else if (obj is RubyStruct)
  502. {
  503. RubyStruct v = (RubyStruct) obj;
  504. WriteUserClass(obj, RubyClass.GetClass("Struct"));
  505. WriteLong(v.InstanceVariables.Count);
  506. foreach (KeyValuePair<RubySymbol, object> item in v.InstanceVariables)
  507. {
  508. WriteObject(item.Key);
  509. WriteObject(item.Value);
  510. }
  511. }
  512. else if (obj is RubyObject)
  513. {
  514. WriteClass(RubyMarshal.Types.Object, obj, true);
  515. WriteObjectInstanceVariable((RubyObject) obj);
  516. }
  517. /* TODO: Data
  518. case T_DATA:
  519. {
  520. VALUE v;
  521. if (!rb_respond_to(obj, s_dump_data)) {
  522. rb_raise(rb_eTypeError,
  523. "no _dump_data is defined for class %s",
  524. rb_obj_classname(obj));
  525. }
  526. v = rb_funcall(obj, s_dump_data, 0);
  527. check_dump_arg(arg, s_dump_data);
  528. w_class(TYPE_DATA, obj, arg, TRUE);
  529. w_object(v, arg, limit);
  530. }
  531. break;*/
  532. else {
  533. throw new InvalidDataException(string.Format("can't dump {0}", obj.GetType().FullName));
  534. }
  535. if (hasiv)
  536. WriteInstanceVariable(fobj, fobj.InstanceVariables);
  537. }
  538. }
  539. public void Dump(object obj)
  540. {
  541. this.m_writer.Write((byte)4);
  542. this.m_writer.Write((byte)8);
  543. WriteObject(obj);
  544. this.m_stream.Flush();
  545. }
  546. /*
  547. public void WriteAnObject(object obj)
  548. {
  549. WriteAnObject(obj, true);
  550. }
  551. public void WriteAnObject(object obj, bool count)
  552. {
  553. if (obj is int)
  554. {
  555. int num = (int)obj;
  556. if ((num < -1073741824) || (num >= 0x40000000))
  557. {
  558. obj = num;
  559. }
  560. }
  561. if (obj == null || obj is RubyNil)
  562. {
  563. this.m_writer.Write((byte)0x30);
  564. }
  565. else if (obj is bool)
  566. {
  567. this.m_writer.Write(((bool)obj) ? ((byte)0x54) : ((byte)70));
  568. }
  569. else if (obj is int)
  570. {
  571. this.WriteFixnum((int)obj);
  572. }
  573. else if (obj is FuzzySymbol)
  574. {
  575. this.WriteSymbol((FuzzySymbol)obj);
  576. }
  577. else if (this.m_objects.Contains(obj))
  578. {
  579. this.m_writer.Write((byte)0x40);
  580. this.WriteInt32(this.m_objects.IndexOf(obj));
  581. }
  582. else if (obj is string)
  583. {
  584. FuzzyString str = new FuzzyString(obj as string);
  585. if (count) this.m_objects.Add(str);
  586. this.WriteString(str);
  587. }
  588. else
  589. {
  590. if (count) this.m_objects.Add(obj);
  591. if (obj is FuzzyString)
  592. {
  593. if ((obj as FuzzyString).Encoding != null)
  594. {
  595. FuzzyExpendObject ooo = new FuzzyExpendObject();
  596. ooo.BaseObject = obj;
  597. this.WriteExpendObject(ooo);
  598. }
  599. else
  600. {
  601. this.WriteString((FuzzyString)obj);
  602. }
  603. }
  604. else if (obj is RubyFloat)
  605. {
  606. this.WriteFloat((RubyFloat)obj);
  607. }
  608. else if (obj is double)
  609. {
  610. this.WriteFloat(new RubyFloat((double)obj));
  611. }
  612. else if (obj is float)
  613. {
  614. this.WriteFloat(new RubyFloat((double)obj));
  615. }
  616. else if (obj is List<object>)
  617. {
  618. this.WriteArray((List<object>)obj);
  619. }
  620. else if (obj is RubyHash)
  621. {
  622. this.WriteHash((RubyHash)obj);
  623. }
  624. else if (obj is RubyRegexp)
  625. {
  626. if ((obj as RubyRegexp).Pattern.Encoding != null)
  627. {
  628. FuzzyExpendObject ooo = new FuzzyExpendObject();
  629. ooo.BaseObject = obj;
  630. this.WriteExpendObject(ooo);
  631. }
  632. else
  633. {
  634. this.WriteRegex((RubyRegexp)obj);
  635. }
  636. }
  637. else if (obj is RubyBignum)
  638. {
  639. this.WriteBignum((RubyBignum)obj);
  640. }
  641. else if (obj is RubyClass)
  642. {
  643. this.WriteClass((RubyClass)obj);
  644. }
  645. else if (obj is RubyModule)
  646. {
  647. this.WriteModule((RubyModule)obj);
  648. }
  649. else if (obj is IRubyUserdefinedDumpObject)
  650. {
  651. this.WriteUsingDump((IRubyUserdefinedDumpObject)obj);
  652. }
  653. else if (obj is FuzzyUserdefinedDumpObject)
  654. {
  655. this.WriteUsingDump((FuzzyUserdefinedDumpObject)obj);
  656. }
  657. else if (obj is FuzzyUserdefinedMarshalDumpObject)
  658. {
  659. this.WriteUsingMarshalDump((FuzzyUserdefinedMarshalDumpObject)obj);
  660. }
  661. else if (obj is FuzzyExtendedObject)
  662. {
  663. this.WriteExtendedObject((FuzzyExtendedObject)obj);
  664. }
  665. else if (obj is FuzzyExpendObject)
  666. {
  667. this.WriteExpendObject((FuzzyExpendObject)obj);
  668. }
  669. else if (obj is FuzzyStruct)
  670. {
  671. this.WriteStruct((FuzzyStruct)obj);
  672. }
  673. else if (obj is FuzzyObject)
  674. {
  675. this.WriteObject((FuzzyObject)obj);
  676. }
  677. else
  678. {
  679. throw new ArgumentException("i don't know how to marshal.dump this type: " + obj.GetType().FullName);
  680. }
  681. }
  682. }
  683. private void WriteUsingDump(IRubyUserdefinedDumpObject iRubyUserdefinedDumpObject)
  684. {
  685. this.m_writer.Write((byte)0x75);
  686. this.WriteSymbol(FuzzySymbol.GetSymbol(iRubyUserdefinedDumpObject.ClassName));
  687. this.WriteStringValue(iRubyUserdefinedDumpObject.Dump());
  688. }
  689. private void WriteUsingMarshalDump(FuzzyUserdefinedMarshalDumpObject obj)
  690. {
  691. this.m_writer.Write((byte)0x55);
  692. this.WriteSymbol(obj.ClassName);
  693. this.WriteAnObject(obj.DumpedObject);
  694. }
  695. private void WriteUsingDump(FuzzyUserdefinedDumpObject obj)
  696. {
  697. this.m_writer.Write((byte)0x75);
  698. this.WriteSymbol(obj.ClassName);
  699. this.WriteStringValue(obj.DumpedObject as byte[]);
  700. }
  701. class FuzzyExpendObject : FuzzyObject { public object BaseObject;}
  702. private void WriteExpendObject(FuzzyExpendObject obj)
  703. {
  704. if (obj.BaseObject is FuzzySymbol || obj.BaseObject is FuzzyString || obj.BaseObject is RubyRegexp)
  705. {
  706. Encoding e = null;
  707. if (obj.BaseObject is FuzzySymbol)
  708. e = (obj.BaseObject as FuzzySymbol).GetRubyString().Encoding;
  709. if (obj.BaseObject is FuzzyString)
  710. e = (obj.BaseObject as FuzzyString).Encoding;
  711. if (obj.BaseObject is RubyRegexp)
  712. e = (obj.BaseObject as RubyRegexp).Pattern.Encoding;
  713. if (e == Encoding.UTF8)
  714. obj.InstanceVariable["E"] = true;
  715. else if (e == null)
  716. obj.InstanceVariable["E"] = false;
  717. else
  718. obj.InstanceVariable["encoding"] = new FuzzyString(System.Text.Encoding.ASCII.GetBytes(e.WebName));
  719. }
  720. if (obj.InstanceVariables.Count == 0)
  721. {
  722. this.m_writer.Write((byte)0x43);
  723. this.WriteSymbol(obj.ClassName);
  724. this.WriteAnObject(obj.BaseObject, false);
  725. }
  726. else
  727. {
  728. this.m_writer.Write((byte)0x49);
  729. if (obj.ClassName != null)
  730. {
  731. this.m_writer.Write((byte)0x43);
  732. this.WriteSymbol(obj.ClassName);
  733. }
  734. if (obj.BaseObject is FuzzyString)
  735. {
  736. this.WriteString(obj.BaseObject as FuzzyString);
  737. }
  738. else if (obj.BaseObject is FuzzySymbol)
  739. {
  740. this.m_writer.Write((byte)0x3a);
  741. this.WriteStringValue((obj.BaseObject as FuzzySymbol).GetRubyString().Raw);
  742. }
  743. else if (obj.BaseObject is RubyRegexp)
  744. {
  745. this.WriteRegex(obj.BaseObject as RubyRegexp);
  746. }
  747. else
  748. {
  749. this.WriteAnObject(obj.BaseObject, false);
  750. }
  751. this.WriteInt32(obj.InstanceVariables.Count);
  752. foreach (KeyValuePair<FuzzySymbol, object> item in obj.InstanceVariables)
  753. {
  754. this.WriteSymbol(item.Key);
  755. this.WriteAnObject(item.Value);
  756. }
  757. }
  758. }
  759. private void WriteObject(FuzzyObject obj)
  760. {
  761. this.m_writer.Write((byte)0x6f);
  762. this.WriteSymbol(obj.ClassName);
  763. this.WriteInt32(obj.InstanceVariables.Count);
  764. foreach (KeyValuePair<FuzzySymbol, object> item in obj.InstanceVariables)
  765. {
  766. this.WriteSymbol(item.Key);
  767. this.WriteAnObject(item.Value);
  768. }
  769. }
  770. private void WriteStruct(FuzzyStruct obj)
  771. {
  772. this.m_writer.Write((byte)0x53);
  773. this.WriteSymbol(obj.ClassName);
  774. this.WriteInt32(obj.InstanceVariables.Count);
  775. foreach (KeyValuePair<FuzzySymbol, object> item in obj.InstanceVariables)
  776. {
  777. this.WriteSymbol(item.Key);
  778. this.WriteAnObject(item.Value);
  779. }
  780. }
  781. class FuzzyExtendedObject : FuzzyObject { public object BaseObject; public RubyModule ExtendedModule;}
  782. private void WriteExtendedObject(FuzzyExtendedObject obj)
  783. {
  784. this.m_writer.Write((byte)0x65);
  785. this.WriteSymbol(obj.ExtendedModule.Symbol);
  786. this.WriteAnObject(obj.BaseObject);
  787. }
  788. private void WriteModule(RubyModule obj)
  789. {
  790. this.m_writer.Write((byte)0x6d);
  791. this.WriteStringValue(obj.ToString());
  792. }
  793. private void WriteClass(RubyClass obj)
  794. {
  795. this.m_writer.Write((byte)0x63);
  796. this.WriteStringValue(obj.ToString());
  797. }
  798. private void WriteBignum(RubyBignum value)
  799. {
  800. this.m_writer.Write((byte)0x6c);
  801. this.WriteBignumValue(value);
  802. }
  803. private void WriteBignumValue(RubyBignum value)
  804. {
  805. char ch;
  806. if (value.Sign > 0)
  807. ch = '+';
  808. else if (value.Sign < 0)
  809. ch = '-';
  810. else
  811. ch = '0';
  812. this.m_writer.Write((byte)ch);
  813. uint[] words = value.GetWords();
  814. int num = words.Length * 2;
  815. int index = words.Length - 1;
  816. bool flag = false;
  817. if ((words.Length > 0) && ((words[index] >> 0x10) == 0))
  818. {
  819. num--;
  820. flag = true;
  821. }
  822. this.WriteInt32(num);
  823. for (int i = 0; i < words.Length; i++)
  824. {
  825. if (flag && (i == index))
  826. {
  827. this.m_writer.Write((ushort)words[i]);
  828. }
  829. else
  830. {
  831. this.m_writer.Write(words[i]);
  832. }
  833. }
  834. }
  835. private void WriteRegex(RubyRegexp value)
  836. {
  837. this.m_writer.Write((byte)0x2f);
  838. this.WriteStringValue(value.Pattern.Raw);
  839. this.m_writer.Write((byte)value.Options);
  840. }
  841. private void WriteFloat(RubyFloat v)
  842. {
  843. double value = v.Value;
  844. this.m_writer.Write((byte)0x66);
  845. if (double.IsInfinity(value))
  846. {
  847. if (double.IsPositiveInfinity(value))
  848. {
  849. this.WriteStringValue("inf");
  850. }
  851. else
  852. {
  853. this.WriteStringValue("-inf");
  854. }
  855. }
  856. else if (double.IsNaN(value))
  857. {
  858. this.WriteStringValue("nan");
  859. }
  860. else
  861. {
  862. this.WriteStringValue(string.Format("{0:g}", value));
  863. }
  864. }
  865. private void WriteHash(RubyHash value)
  866. {
  867. char ch = (value.DefaultValue != null) ? '}' : '{';
  868. this.m_writer.Write((byte)ch);
  869. this.WriteInt32(value.Count);
  870. foreach (KeyValuePair<object, object> pair in value)
  871. {
  872. this.WriteAnObject(pair.Key);
  873. this.WriteAnObject(pair.Value);
  874. }
  875. if (value.DefaultValue != null)
  876. {
  877. this.WriteAnObject(value.DefaultValue);
  878. }
  879. }
  880. private void WriteArray(List<object> value)
  881. {
  882. this.m_writer.Write((byte)0x5b);
  883. this.WriteInt32(value.Count);
  884. foreach (object obj2 in value)
  885. {
  886. this.WriteAnObject(obj2);
  887. }
  888. }
  889. private void WriteString(FuzzyString value)
  890. {
  891. this.m_writer.Write((byte)0x22);
  892. this.WriteStringValue(value.Raw);
  893. }
  894. private void WriteStringValue(string value)
  895. {
  896. byte[] bytes = Encoding.Unicode.GetBytes(value);
  897. byte[] buffer = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, bytes);
  898. this.WriteInt32(buffer.Length);
  899. this.m_writer.Write(buffer);
  900. }
  901. private void WriteStringValue(byte[] value)
  902. {
  903. this.WriteInt32(value.Length);
  904. this.m_writer.Write(value);
  905. }
  906. private void WriteSymbol(FuzzySymbol value)
  907. {
  908. if (this.m_symbols.Contains(value))
  909. {
  910. this.m_writer.Write((byte)0x3b);
  911. this.WriteInt32(this.m_symbols.IndexOf(value));
  912. }
  913. else
  914. {
  915. this.m_symbols.Add(value);
  916. if (value.GetRubyString() != null)
  917. {
  918. FuzzyExpendObject ooo = new FuzzyExpendObject();
  919. ooo.BaseObject = value;
  920. this.WriteExpendObject(ooo);
  921. }
  922. else
  923. {
  924. this.m_writer.Write((byte)0x3a);
  925. this.WriteStringValue(value.GetString());
  926. }
  927. }
  928. }
  929. private void WriteFixnum(int value)
  930. {
  931. this.m_writer.Write((byte)0x69);
  932. this.WriteInt32(value);
  933. }
  934. private void WriteInt32(int value)
  935. {
  936. if (value == 0)
  937. {
  938. this.m_writer.Write((byte)0);
  939. }
  940. else if ((value > 0) && (value < 0x7b))
  941. {
  942. this.m_writer.Write((byte)(value + 5));
  943. }
  944. else if ((value < 0) && (value > -124))
  945. {
  946. this.m_writer.Write((sbyte)(value - 5));
  947. }
  948. else
  949. {
  950. sbyte num2;
  951. byte[] buffer = new byte[5];
  952. buffer[1] = (byte)(value & 0xff);
  953. buffer[2] = (byte)((value >> 8) & 0xff);
  954. buffer[3] = (byte)((value >> 0x10) & 0xff);
  955. buffer[4] = (byte)((value >> 0x18) & 0xff);
  956. int index = 4;
  957. if (value >= 0)
  958. {
  959. while (buffer[index] == 0)
  960. {
  961. index--;
  962. }
  963. num2 = (sbyte)index;
  964. }
  965. else
  966. {
  967. while (buffer[index] == 0xff)
  968. {
  969. index--;
  970. }
  971. num2 = (sbyte)-index;
  972. }
  973. buffer[0] = (byte)num2;
  974. this.m_writer.Write(buffer, 0, index + 1);
  975. }
  976. }*/
  977. }
  978. }