PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/EasyNet.Solr-Net35/EasyNet.Solr/Commons/JavaBinCodec.cs

#
C# | 815 lines | 716 code | 80 blank | 19 comment | 125 complexity | d5fe345b7bdae00f7d234682b6e66f93 MD5 | raw file
  1. namespace EasyNet.Solr.Commons
  2. {
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. /// <summary>
  8. /// javabin格式数据编解码器
  9. /// </summary>
  10. public class JavaBinCodec : ICodec, IDisposable
  11. {
  12. public const byte
  13. NULL = 0,
  14. BOOL_TRUE = 1,
  15. BOOL_FALSE = 2,
  16. BYTE = 3,
  17. SHORT = 4,
  18. DOUBLE = 5,
  19. INT = 6,
  20. LONG = 7,
  21. FLOAT = 8,
  22. DATE = 9,
  23. MAP = 10,
  24. SOLRDOC = 11,
  25. SOLRDOCLST = 12,
  26. BYTEARR = 13,
  27. ITERATOR = 14,
  28. END = 15,
  29. TAG_AND_LEN = (byte)(1 << 5),
  30. STR = (byte)(1 << 5),
  31. SINT = (byte)(2 << 5),
  32. SLONG = (byte)(3 << 5),
  33. ARR = (byte)(4 << 5), //
  34. ORDERED_MAP = (byte)(5 << 5),
  35. NAMED_LST = (byte)(6 << 5),
  36. EXTERN_STRING = (byte)(7 << 5);
  37. private static byte VERSION = 2;
  38. protected FastOutputStream daos;
  39. public JavaBinCodec()
  40. {
  41. }
  42. public void Marshal(object nl, Stream os)
  43. {
  44. daos = new FastOutputStream(os);
  45. try
  46. {
  47. daos.WriteByte(VERSION);
  48. WriteVal(nl);
  49. }
  50. finally
  51. {
  52. daos.Flush();
  53. daos.Close();
  54. }
  55. }
  56. byte version;
  57. public object Unmarshal(Stream inputStream)
  58. {
  59. FastInputStream dis = new FastInputStream(inputStream);
  60. version = (byte)dis.ReadByte();
  61. if (version != VERSION)
  62. {
  63. throw new ApplicationException("Invalid version or the data in not in 'javabin' format");
  64. }
  65. return ReadVal(dis);
  66. }
  67. public SimpleOrderedMap ReadOrderedMap(FastInputStream dis)
  68. {
  69. int sz = ReadSize(dis);
  70. SimpleOrderedMap nl = new SimpleOrderedMap();
  71. for (int i = 0; i < sz; i++)
  72. {
  73. string name = (string)ReadVal(dis);
  74. object val = ReadVal(dis);
  75. nl.Add(name, val);
  76. }
  77. return nl;
  78. }
  79. public NamedList ReadNamedList(FastInputStream dis)
  80. {
  81. int sz = ReadSize(dis);
  82. NamedList nl = new NamedList();
  83. for (int i = 0; i < sz; i++)
  84. {
  85. string name = (string)ReadVal(dis);
  86. object val = ReadVal(dis);
  87. nl.Add(name, val);
  88. }
  89. return nl;
  90. }
  91. public void WriteNamedList(NamedList nl)
  92. {
  93. WriteTag(nl is SimpleOrderedMap ? ORDERED_MAP : NAMED_LST, nl.Count);
  94. for (int i = 0; i < nl.Count; i++)
  95. {
  96. string name = nl.GetName(i);
  97. WriteExternString(name);
  98. object val = nl.GetVal(i);
  99. WriteVal(val);
  100. }
  101. }
  102. public void WriteVal(object val)
  103. {
  104. WriteKnownType(val);
  105. }
  106. protected static readonly object END_OBJ = new object();
  107. protected byte tagByte;
  108. public object ReadVal(FastInputStream dis)
  109. {
  110. tagByte = (byte)dis.ReadByte();
  111. // if ((tagByte & 0xe0) == 0) {
  112. // if top 3 bits are clear, this is a normal tag
  113. // OK, try type + size in single byte
  114. switch (tagByte >> 5)
  115. {
  116. case STR >> 5:
  117. return ReadStr(dis);
  118. case SINT >> 5:
  119. return ReadSmallInt(dis);
  120. case SLONG >> 5:
  121. return ReadSmallLong(dis);
  122. case ARR >> 5:
  123. return ReadArray(dis);
  124. case ORDERED_MAP >> 5:
  125. return ReadOrderedMap(dis);
  126. case NAMED_LST >> 5:
  127. return ReadNamedList(dis);
  128. case EXTERN_STRING >> 5:
  129. return ReadExternString(dis);
  130. }
  131. switch (tagByte)
  132. {
  133. case NULL:
  134. return null;
  135. case DATE:
  136. try
  137. {
  138. return dis.ReadLong().ConvertToDateTime();
  139. }
  140. catch
  141. {
  142. return new DateTime();
  143. }
  144. case INT:
  145. return dis.ReadInt();
  146. case BOOL_TRUE:
  147. return true;
  148. case BOOL_FALSE:
  149. return false;
  150. case FLOAT:
  151. return dis.ReadFloat();
  152. case DOUBLE:
  153. return dis.ReadDouble();
  154. case LONG:
  155. return dis.ReadLong();
  156. case BYTE:
  157. return dis.ReadByte();
  158. case SHORT:
  159. return dis.ReadShort();
  160. case MAP:
  161. return ReadMap(dis);
  162. case SOLRDOC:
  163. return ReadSolrDocument(dis);
  164. case SOLRDOCLST:
  165. return ReadSolrDocumentList(dis);
  166. case BYTEARR:
  167. return ReadByteArray(dis);
  168. case ITERATOR:
  169. return ReadIterator(dis);
  170. case END:
  171. return END_OBJ;
  172. }
  173. throw new ApplicationException("Unknown type " + tagByte);
  174. }
  175. public bool WriteKnownType(object val)
  176. {
  177. if (WritePrimitive(val)) return true;
  178. if (val is NamedList)
  179. {
  180. WriteNamedList((NamedList)val);
  181. return true;
  182. }
  183. if (val is SolrDocumentList)
  184. { // SolrDocumentList is a IList, so must come before IList check
  185. WriteSolrDocumentList((SolrDocumentList)val);
  186. return true;
  187. }
  188. if (val is IList)
  189. {
  190. WriteArray((IList)val);
  191. return true;
  192. }
  193. if (val is object[])
  194. {
  195. WriteArray((object[])val);
  196. return true;
  197. }
  198. if (val is SolrDocument)
  199. {
  200. WriteSolrDocument((SolrDocument)val);
  201. return true;
  202. }
  203. if (val is IDictionary)
  204. {
  205. WriteMap((IDictionary)val);
  206. return true;
  207. }
  208. if (val is IEnumerator)
  209. {
  210. WriteIterator((IEnumerator)val);
  211. return true;
  212. }
  213. if (val is IEnumerable)
  214. {
  215. WriteIterator(((IEnumerable)val).GetEnumerator());
  216. return true;
  217. }
  218. return false;
  219. }
  220. public void WriteTag(byte tag)
  221. {
  222. daos.WriteByte(tag);
  223. }
  224. public void WriteTag(byte tag, int size)
  225. {
  226. if ((tag & 0xe0) != 0)
  227. {
  228. if (size < 0x1f)
  229. {
  230. daos.WriteByte(tag | size);
  231. }
  232. else
  233. {
  234. daos.WriteByte(tag | 0x1f);
  235. WriteVInt(size - 0x1f, daos);
  236. }
  237. }
  238. else
  239. {
  240. daos.WriteByte(tag);
  241. WriteVInt(size, daos);
  242. }
  243. }
  244. public void WriteByteArray(byte[] arr, int offset, int len)
  245. {
  246. WriteTag(BYTEARR, len);
  247. daos.Write(arr, offset, len);
  248. }
  249. public byte[] ReadByteArray(FastInputStream dis)
  250. {
  251. byte[] arr = new byte[ReadVInt(dis)];
  252. dis.ReadFully(arr);
  253. return arr;
  254. }
  255. public void WriteSolrDocument(SolrDocument doc)
  256. {
  257. WriteSolrDocument(doc, null);
  258. }
  259. public void WriteSolrDocument(SolrDocument doc, HashSet<string> fields)
  260. {
  261. int count = 0;
  262. if (fields == null)
  263. {
  264. count = doc.GetFieldNames().Count;
  265. }
  266. else
  267. {
  268. foreach (KeyValuePair<string, object> entry in doc)
  269. {
  270. if (fields.Contains(entry.Key)) count++;
  271. }
  272. }
  273. WriteTag(SOLRDOC);
  274. WriteTag(ORDERED_MAP, count);
  275. foreach (KeyValuePair<string, object> entry in doc)
  276. {
  277. if (fields == null || fields.Contains(entry.Key))
  278. {
  279. string name = entry.Key;
  280. WriteExternString(name);
  281. object val = entry.Value;
  282. WriteVal(val);
  283. }
  284. }
  285. }
  286. public SolrDocument ReadSolrDocument(FastInputStream dis)
  287. {
  288. object o = ReadVal(dis);
  289. NamedList nl = (NamedList)o;
  290. SolrDocument doc = new SolrDocument();
  291. for (int i = 0; i < nl.Count; i++)
  292. {
  293. string name = nl.GetName(i);
  294. object val = nl.GetVal(i);
  295. doc[name] = val;
  296. }
  297. return doc;
  298. }
  299. public SolrDocumentList ReadSolrDocumentList(FastInputStream dis)
  300. {
  301. SolrDocumentList solrDocs = new SolrDocumentList();
  302. IList list = (IList)ReadVal(dis);
  303. solrDocs.NumFound = (long)list[0];
  304. solrDocs.Start = (long)list[1];
  305. solrDocs.MaxScore = (float?)list[2];
  306. ArrayList l = (ArrayList)ReadVal(dis);
  307. foreach (SolrDocument doc in l)
  308. {
  309. solrDocs.Add(doc);
  310. }
  311. return solrDocs;
  312. }
  313. public void WriteSolrDocumentList(SolrDocumentList docs)
  314. {
  315. WriteTag(SOLRDOCLST);
  316. IList l = new ArrayList(3);
  317. l.Add(docs.NumFound);
  318. l.Add(docs.Start);
  319. l.Add(docs.MaxScore);
  320. WriteArray(l);
  321. WriteArray(docs);
  322. }
  323. public IDictionary<object, object> ReadMap(FastInputStream dis)
  324. {
  325. int sz = ReadVInt(dis);
  326. IDictionary<object, object> m = new LinkedHashMap<object, object>();
  327. for (int i = 0; i < sz; i++)
  328. {
  329. object key = ReadVal(dis);
  330. object val = ReadVal(dis);
  331. m[key] = val;
  332. }
  333. return m;
  334. }
  335. public void WriteIterator(IEnumerator iter)
  336. {
  337. WriteTag(ITERATOR);
  338. while (iter.MoveNext())
  339. {
  340. WriteVal(iter.Current);
  341. }
  342. WriteVal(END_OBJ);
  343. }
  344. public IList ReadIterator(FastInputStream fis)
  345. {
  346. ArrayList l = new ArrayList();
  347. while (true)
  348. {
  349. object o = ReadVal(fis);
  350. if (o == END_OBJ) break;
  351. l.Add(o);
  352. }
  353. return l;
  354. }
  355. public void WriteArray(IList l)
  356. {
  357. WriteTag(ARR, l.Count);
  358. for (int i = 0; i < l.Count; i++)
  359. {
  360. WriteVal(l[i]);
  361. }
  362. }
  363. public void WriteArray(object[] arr)
  364. {
  365. WriteTag(ARR, arr.Length);
  366. for (int i = 0; i < arr.Length; i++)
  367. {
  368. object o = arr[i];
  369. WriteVal(o);
  370. }
  371. }
  372. public IList ReadArray(FastInputStream dis)
  373. {
  374. int sz = ReadSize(dis);
  375. ArrayList l = new ArrayList(sz);
  376. for (int i = 0; i < sz; i++)
  377. {
  378. l.Add(ReadVal(dis));
  379. }
  380. return l;
  381. }
  382. public void WriteStr(string s)
  383. {
  384. if (s == null)
  385. {
  386. WriteTag(NULL);
  387. return;
  388. }
  389. int end = s.Length;
  390. int maxSize = end * 4;
  391. if (bytes == null || bytes.Length < maxSize) bytes = new byte[maxSize];
  392. int upto = 0;
  393. for (int i = 0; i < end; i++)
  394. {
  395. int code = s[i];
  396. if (code < 0x80)
  397. bytes[upto++] = (byte)code;
  398. else if (code < 0x800)
  399. {
  400. bytes[upto++] = (byte)(0xC0 | (code >> 6));
  401. bytes[upto++] = (byte)(0x80 | (code & 0x3F));
  402. }
  403. else if (code < 0xD800 || code > 0xDFFF)
  404. {
  405. bytes[upto++] = (byte)(0xE0 | (code >> 12));
  406. bytes[upto++] = (byte)(0x80 | ((code >> 6) & 0x3F));
  407. bytes[upto++] = (byte)(0x80 | (code & 0x3F));
  408. }
  409. else
  410. {
  411. // surrogate pair
  412. // confirm valid high surrogate
  413. if (code < 0xDC00 && (i < end - 1))
  414. {
  415. int utf32 = s[i + 1];
  416. // confirm valid low surrogate and write pair
  417. if (utf32 >= 0xDC00 && utf32 <= 0xDFFF)
  418. {
  419. utf32 = ((code - 0xD7C0) << 10) + (utf32 & 0x3FF);
  420. i++;
  421. bytes[upto++] = (byte)(0xF0 | (utf32 >> 18));
  422. bytes[upto++] = (byte)(0x80 | ((utf32 >> 12) & 0x3F));
  423. bytes[upto++] = (byte)(0x80 | ((utf32 >> 6) & 0x3F));
  424. bytes[upto++] = (byte)(0x80 | (utf32 & 0x3F));
  425. continue;
  426. }
  427. }
  428. // replace unpaired surrogate or out-of-order low surrogate
  429. // with substitution character
  430. bytes[upto++] = (byte)0xEF;
  431. bytes[upto++] = (byte)0xBF;
  432. bytes[upto++] = (byte)0xBD;
  433. }
  434. }
  435. WriteTag(STR, upto);
  436. daos.Write(bytes, 0, upto);
  437. }
  438. byte[] bytes;
  439. char[] chars;
  440. public string ReadStr(FastInputStream dis)
  441. {
  442. int sz = ReadSize(dis);
  443. if (chars == null || chars.Length < sz) chars = new char[sz];
  444. if (bytes == null || bytes.Length < sz) bytes = new byte[sz];
  445. dis.ReadFully(bytes, 0, sz);
  446. int outUpto = 0;
  447. for (int i = 0; i < sz; )
  448. {
  449. int b = bytes[i++] & 0xff;
  450. int ch;
  451. if (b < 0xc0)
  452. {
  453. ch = b;
  454. }
  455. else if (b < 0xe0)
  456. {
  457. ch = ((b & 0x1f) << 6) + (bytes[i++] & 0x3f);
  458. }
  459. else if (b < 0xf0)
  460. {
  461. ch = ((b & 0xf) << 12) + ((bytes[i++] & 0x3f) << 6) + (bytes[i++] & 0x3f);
  462. }
  463. else
  464. {
  465. ch = ((b & 0x7) << 18) + ((bytes[i++] & 0x3f) << 12) + ((bytes[i++] & 0x3f) << 6) + (bytes[i++] & 0x3f);
  466. }
  467. if (ch <= 0xFFFF)
  468. {
  469. // target is a character <= 0xFFFF
  470. chars[outUpto++] = (char)ch;
  471. }
  472. else
  473. {
  474. // target is a character in range 0xFFFF - 0x10FFFF
  475. int chHalf = ch - 0x10000;
  476. chars[outUpto++] = (char)((chHalf >> 0xA) + 0xD800);
  477. chars[outUpto++] = (char)((chHalf & 0x3FF) + 0xDC00);
  478. }
  479. }
  480. return new String(chars, 0, outUpto);
  481. }
  482. public void WriteInt(int val)
  483. {
  484. if (val > 0)
  485. {
  486. int b = SINT | (val & 0x0f);
  487. if (val >= 0x0f)
  488. {
  489. b |= 0x10;
  490. daos.WriteByte(b);
  491. WriteVInt(val >> 4, daos);
  492. }
  493. else
  494. {
  495. daos.WriteByte(b);
  496. }
  497. }
  498. else
  499. {
  500. daos.WriteByte(INT);
  501. daos.WriteInt(val);
  502. }
  503. }
  504. public int ReadSmallInt(FastInputStream dis)
  505. {
  506. int v = tagByte & 0x0F;
  507. if ((tagByte & 0x10) != 0)
  508. v = (ReadVInt(dis) << 4) | v;
  509. return v;
  510. }
  511. public void WriteLong(long val)
  512. {
  513. if (((ulong)val & 0xff00000000000000L) == 0)
  514. {
  515. int b = SLONG | ((int)val & 0x0f);
  516. if (val >= 0x0f)
  517. {
  518. b |= 0x10;
  519. daos.WriteByte(b);
  520. WriteVLong(val >> 4, daos);
  521. }
  522. else
  523. {
  524. daos.WriteByte(b);
  525. }
  526. }
  527. else
  528. {
  529. daos.WriteByte(LONG);
  530. daos.WriteLong(val);
  531. }
  532. }
  533. public long ReadSmallLong(FastInputStream dis)
  534. {
  535. long v = tagByte & 0x0F;
  536. if ((tagByte & 0x10) != 0)
  537. v = (ReadVLong(dis) << 4) | v;
  538. return v;
  539. }
  540. public bool WritePrimitive(object val)
  541. {
  542. if (val == null)
  543. {
  544. daos.WriteByte(NULL);
  545. return true;
  546. }
  547. else if (val is string)
  548. {
  549. WriteStr((string)val);
  550. return true;
  551. }
  552. else if (val is int)
  553. {
  554. WriteInt((int)val);
  555. return true;
  556. }
  557. else if (val is long)
  558. {
  559. WriteLong((long)val);
  560. return true;
  561. }
  562. else if (val is float)
  563. {
  564. daos.WriteByte(FLOAT);
  565. daos.WriteFloat((float)val);
  566. return true;
  567. }
  568. else if (val is DateTime)
  569. {
  570. daos.WriteByte(DATE);
  571. daos.WriteLong(((DateTime)val).ConvertToLong());
  572. return true;
  573. }
  574. else if (val is Boolean)
  575. {
  576. if ((Boolean)val) daos.WriteByte(BOOL_TRUE);
  577. else daos.WriteByte(BOOL_FALSE);
  578. return true;
  579. }
  580. else if (val is double)
  581. {
  582. daos.WriteByte(DOUBLE);
  583. daos.WriteDouble((Double)val);
  584. return true;
  585. }
  586. else if (val is byte)
  587. {
  588. daos.WriteByte(BYTE);
  589. daos.WriteByte((Byte)val);
  590. return true;
  591. }
  592. else if (val is short)
  593. {
  594. daos.WriteByte(SHORT);
  595. daos.WriteShort((short)val);
  596. return true;
  597. }
  598. else if (val is byte[])
  599. {
  600. WriteByteArray((byte[])val, 0, ((byte[])val).Length);
  601. return true;
  602. }
  603. //else if (val is ByteBuffer)
  604. //{
  605. // ByteBuffer buf = (ByteBuffer)val;
  606. // writeByteArray(buf.array(), buf.position(), buf.limit() - buf.position());
  607. // return true;
  608. //}
  609. else if (val == END_OBJ)
  610. {
  611. WriteTag(END);
  612. return true;
  613. }
  614. return false;
  615. }
  616. public void WriteMap(IDictionary val)
  617. {
  618. WriteTag(MAP, val.Count);
  619. foreach (DictionaryEntry entry in val)
  620. {
  621. object key = entry.Key;
  622. if (key is string)
  623. {
  624. WriteExternString((string)key);
  625. }
  626. else
  627. {
  628. WriteVal(key);
  629. }
  630. WriteVal(entry.Value);
  631. }
  632. }
  633. public int ReadSize(FastInputStream intputStream)
  634. {
  635. int sz = tagByte & 0x1f;
  636. if (sz == 0x1f) sz += ReadVInt(intputStream);
  637. return sz;
  638. }
  639. public static void WriteVInt(int i, FastOutputStream fs)
  640. {
  641. while ((i & ~0x7F) != 0)
  642. {
  643. fs.WriteByte((byte)((i & 0x7f) | 0x80));
  644. i >>= 7;
  645. }
  646. fs.WriteByte((byte)i);
  647. }
  648. public static int ReadVInt(FastInputStream fs)
  649. {
  650. byte b = (byte)fs.ReadByte();
  651. int i = b & 0x7F;
  652. for (int shift = 7; (b & 0x80) != 0; shift += 7)
  653. {
  654. b = (byte)fs.ReadByte();
  655. i |= (b & 0x7F) << shift;
  656. }
  657. return i;
  658. }
  659. public static void WriteVLong(long i, FastOutputStream fs)
  660. {
  661. while ((i & ~0x7F) != 0)
  662. {
  663. fs.WriteByte((byte)((i & 0x7f) | 0x80));
  664. i >>= 7;
  665. }
  666. fs.WriteByte((byte)i);
  667. }
  668. public static long ReadVLong(FastInputStream fs)
  669. {
  670. byte b = (byte)fs.ReadByte();
  671. long i = b & 0x7F;
  672. for (int shift = 7; (b & 0x80) != 0; shift += 7)
  673. {
  674. b = (byte)fs.ReadByte();
  675. i |= (long)(b & 0x7F) << shift;
  676. }
  677. return i;
  678. }
  679. private int stringsCount = 0;
  680. private IDictionary<string, int?> stringsMap;
  681. private IList<string> stringsList;
  682. public void WriteExternString(string s)
  683. {
  684. if (s == null)
  685. {
  686. WriteTag(NULL);
  687. return;
  688. }
  689. int? idx;
  690. if (stringsMap == null)
  691. {
  692. idx = null;
  693. }
  694. else
  695. {
  696. stringsMap.TryGetValue(s, out idx);
  697. }
  698. if (idx == null) idx = 0;
  699. WriteTag(EXTERN_STRING, idx.Value);
  700. if (idx == 0)
  701. {
  702. WriteStr(s);
  703. if (stringsMap == null) stringsMap = new Dictionary<String, int?>();
  704. stringsMap[s] = (++stringsCount);
  705. }
  706. }
  707. public string ReadExternString(FastInputStream fis)
  708. {
  709. int idx = ReadSize(fis);
  710. if (idx != 0)
  711. {// idx != 0 is the index of the extern string
  712. return stringsList[idx - 1];
  713. }
  714. else
  715. {// idx == 0 means it has a string value
  716. string s = (string)ReadVal(fis);
  717. if (stringsList == null) stringsList = new List<string>();
  718. stringsList.Add(s);
  719. return s;
  720. }
  721. }
  722. protected virtual void Dispose(bool disposing)
  723. {
  724. if (disposing)
  725. {
  726. daos.Close();
  727. }
  728. }
  729. public void Dispose()
  730. {
  731. Dispose(true);
  732. GC.SuppressFinalize(this);
  733. }
  734. }
  735. }