You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

697 lines
18 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. #region License
  2. // Copyright (c) 2007 James Newton-King
  3. //
  4. // Permission is hereby granted, free of charge, to any person
  5. // obtaining a copy of this software and associated documentation
  6. // files (the "Software"), to deal in the Software without
  7. // restriction, including without limitation the rights to use,
  8. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following
  11. // conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. // OTHER DEALINGS IN THE SOFTWARE.
  24. #endregion
  25. using System;
  26. using System.Collections.Generic;
  27. using System.Collections;
  28. using System.Threading;
  29. #if NET20
  30. using Newtonsoft.Json.Utilities.LinqBridge;
  31. #else
  32. using System.Linq;
  33. #endif
  34. namespace Newtonsoft.Json.Utilities
  35. {
  36. internal interface IWrappedDictionary
  37. : IDictionary
  38. {
  39. object UnderlyingDictionary { get; }
  40. }
  41. internal class DictionaryWrapper<TKey, TValue> : IDictionary<TKey, TValue>, IWrappedDictionary
  42. {
  43. private readonly IDictionary _dictionary;
  44. private readonly IDictionary<TKey, TValue> _genericDictionary;
  45. #if NETSTD
  46. private readonly IReadOnlyDictionary<TKey, TValue> _readOnlyDictionary;
  47. #endif
  48. private object _syncRoot;
  49. public DictionaryWrapper(IDictionary dictionary)
  50. {
  51. ValidationUtils.ArgumentNotNull(dictionary, nameof(dictionary));
  52. _dictionary = dictionary;
  53. }
  54. public DictionaryWrapper(IDictionary<TKey, TValue> dictionary)
  55. {
  56. ValidationUtils.ArgumentNotNull(dictionary, nameof(dictionary));
  57. _genericDictionary = dictionary;
  58. }
  59. #if NETSTD
  60. public DictionaryWrapper(IReadOnlyDictionary<TKey, TValue> dictionary)
  61. {
  62. ValidationUtils.ArgumentNotNull(dictionary, nameof(dictionary));
  63. _readOnlyDictionary = dictionary;
  64. }
  65. #endif
  66. public void Add(TKey key, TValue value)
  67. {
  68. if (_dictionary != null)
  69. {
  70. _dictionary.Add(key, value);
  71. }
  72. else if (_genericDictionary != null)
  73. {
  74. _genericDictionary.Add(key, value);
  75. }
  76. else
  77. {
  78. throw new NotSupportedException();
  79. }
  80. }
  81. public bool ContainsKey(TKey key)
  82. {
  83. if (_dictionary != null)
  84. {
  85. return _dictionary.Contains(key);
  86. }
  87. #if NETSTD
  88. else if (_readOnlyDictionary != null)
  89. {
  90. return _readOnlyDictionary.ContainsKey(key);
  91. }
  92. #endif
  93. else
  94. {
  95. return _genericDictionary.ContainsKey(key);
  96. }
  97. }
  98. public ICollection<TKey> Keys
  99. {
  100. get
  101. {
  102. if (_dictionary != null)
  103. {
  104. return _dictionary.Keys.Cast<TKey>().List();
  105. }
  106. #if NETSTD
  107. else if (_readOnlyDictionary != null)
  108. {
  109. return _readOnlyDictionary.Keys.List();
  110. }
  111. #endif
  112. else
  113. {
  114. return _genericDictionary.Keys;
  115. }
  116. }
  117. }
  118. public bool Remove(TKey key)
  119. {
  120. if (_dictionary != null)
  121. {
  122. if (_dictionary.Contains(key))
  123. {
  124. _dictionary.Remove(key);
  125. return true;
  126. }
  127. else
  128. {
  129. return false;
  130. }
  131. }
  132. #if NETSTD
  133. else if (_readOnlyDictionary != null)
  134. {
  135. throw new NotSupportedException();
  136. }
  137. #endif
  138. else
  139. {
  140. return _genericDictionary.Remove(key);
  141. }
  142. }
  143. public bool TryGetValue(TKey key, out TValue value)
  144. {
  145. if (_dictionary != null)
  146. {
  147. if (!_dictionary.Contains(key))
  148. {
  149. value = default(TValue);
  150. return false;
  151. }
  152. else
  153. {
  154. value = (TValue)_dictionary[key];
  155. return true;
  156. }
  157. }
  158. #if NETSTD
  159. else if (_readOnlyDictionary != null)
  160. {
  161. throw new NotSupportedException();
  162. }
  163. #endif
  164. else
  165. {
  166. return _genericDictionary.TryGetValue(key, out value);
  167. }
  168. }
  169. public ICollection<TValue> Values
  170. {
  171. get
  172. {
  173. if (_dictionary != null)
  174. {
  175. return _dictionary.Values.Cast<TValue>().List();
  176. }
  177. #if NETSTD
  178. else if (_readOnlyDictionary != null)
  179. {
  180. return _readOnlyDictionary.Values.List();
  181. }
  182. #endif
  183. else
  184. {
  185. return _genericDictionary.Values;
  186. }
  187. }
  188. }
  189. public TValue this[TKey key]
  190. {
  191. get
  192. {
  193. if (_dictionary != null)
  194. {
  195. return (TValue)_dictionary[key];
  196. }
  197. #if NETSTD
  198. else if (_readOnlyDictionary != null)
  199. {
  200. return _readOnlyDictionary[key];
  201. }
  202. #endif
  203. else
  204. {
  205. return _genericDictionary[key];
  206. }
  207. }
  208. set
  209. {
  210. if (_dictionary != null)
  211. {
  212. _dictionary[key] = value;
  213. }
  214. #if NETSTD
  215. else if (_readOnlyDictionary != null)
  216. {
  217. throw new NotSupportedException();
  218. }
  219. #endif
  220. else
  221. {
  222. _genericDictionary[key] = value;
  223. }
  224. }
  225. }
  226. public void Add(KeyValuePair<TKey, TValue> item)
  227. {
  228. if (_dictionary != null)
  229. {
  230. ((IList)_dictionary).Add(item);
  231. }
  232. #if NETSTD
  233. else if (_readOnlyDictionary != null)
  234. {
  235. throw new NotSupportedException();
  236. }
  237. #endif
  238. else
  239. {
  240. _genericDictionary?.Add(item);
  241. }
  242. }
  243. public void Clear()
  244. {
  245. if (_dictionary != null)
  246. {
  247. _dictionary.Clear();
  248. }
  249. #if NETSTD
  250. else if (_readOnlyDictionary != null)
  251. {
  252. throw new NotSupportedException();
  253. }
  254. #endif
  255. else
  256. {
  257. _genericDictionary.Clear();
  258. }
  259. }
  260. public bool Contains(KeyValuePair<TKey, TValue> item)
  261. {
  262. if (_dictionary != null)
  263. {
  264. return ((IList)_dictionary).Contains(item);
  265. }
  266. #if NETSTD
  267. else if (_readOnlyDictionary != null)
  268. {
  269. return _readOnlyDictionary.Contains(item);
  270. }
  271. #endif
  272. else
  273. {
  274. return _genericDictionary.Contains(item);
  275. }
  276. }
  277. public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
  278. {
  279. if (_dictionary != null)
  280. {
  281. // Manual use of IDictionaryEnumerator instead of foreach to avoid DictionaryEntry box allocations.
  282. IDictionaryEnumerator e = _dictionary.GetEnumerator();
  283. try
  284. {
  285. while (e.MoveNext())
  286. {
  287. DictionaryEntry entry = e.Entry;
  288. array[arrayIndex++] = new KeyValuePair<TKey, TValue>((TKey)entry.Key, (TValue)entry.Value);
  289. }
  290. }
  291. finally
  292. {
  293. (e as IDisposable)?.Dispose();
  294. }
  295. }
  296. #if NETSTD
  297. else if (_readOnlyDictionary != null)
  298. {
  299. throw new NotSupportedException();
  300. }
  301. #endif
  302. else
  303. {
  304. _genericDictionary.CopyTo(array, arrayIndex);
  305. }
  306. }
  307. public int Count
  308. {
  309. get
  310. {
  311. if (_dictionary != null)
  312. {
  313. return _dictionary.Count;
  314. }
  315. #if NETSTD
  316. else if (_readOnlyDictionary != null)
  317. {
  318. return _readOnlyDictionary.Count;
  319. }
  320. #endif
  321. else
  322. {
  323. return _genericDictionary.Count;
  324. }
  325. }
  326. }
  327. public bool IsReadOnly
  328. {
  329. get
  330. {
  331. if (_dictionary != null)
  332. {
  333. return _dictionary.IsReadOnly;
  334. }
  335. #if NETSTD
  336. else if (_readOnlyDictionary != null)
  337. {
  338. return true;
  339. }
  340. #endif
  341. else
  342. {
  343. return _genericDictionary.IsReadOnly;
  344. }
  345. }
  346. }
  347. public bool Remove(KeyValuePair<TKey, TValue> item)
  348. {
  349. if (_dictionary != null)
  350. {
  351. if (_dictionary.Contains(item.Key))
  352. {
  353. object value = _dictionary[item.Key];
  354. if (Equals(value, item.Value))
  355. {
  356. _dictionary.Remove(item.Key);
  357. return true;
  358. }
  359. else
  360. {
  361. return false;
  362. }
  363. }
  364. else
  365. {
  366. return true;
  367. }
  368. }
  369. #if NETSTD
  370. else if (_readOnlyDictionary != null)
  371. {
  372. throw new NotSupportedException();
  373. }
  374. #endif
  375. else
  376. {
  377. return _genericDictionary.Remove(item);
  378. }
  379. }
  380. public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
  381. {
  382. if (_dictionary != null)
  383. {
  384. return _dictionary.Cast<DictionaryEntry>().Select(de => new KeyValuePair<TKey, TValue>((TKey)de.Key, (TValue)de.Value)).GetEnumerator();
  385. }
  386. #if NETSTD
  387. else if (_readOnlyDictionary != null)
  388. {
  389. return _readOnlyDictionary.GetEnumerator();
  390. }
  391. #endif
  392. else
  393. {
  394. return _genericDictionary.GetEnumerator();
  395. }
  396. }
  397. IEnumerator IEnumerable.GetEnumerator()
  398. {
  399. return GetEnumerator();
  400. }
  401. void IDictionary.Add(object key, object value)
  402. {
  403. if (_dictionary != null)
  404. {
  405. _dictionary.Add(key, value);
  406. }
  407. #if NETSTD
  408. else if (_readOnlyDictionary != null)
  409. {
  410. throw new NotSupportedException();
  411. }
  412. #endif
  413. else
  414. {
  415. _genericDictionary.Add((TKey)key, (TValue)value);
  416. }
  417. }
  418. object IDictionary.this[object key]
  419. {
  420. get
  421. {
  422. if (_dictionary != null)
  423. {
  424. return _dictionary[key];
  425. }
  426. #if NETSTD
  427. else if (_readOnlyDictionary != null)
  428. {
  429. return _readOnlyDictionary[(TKey)key];
  430. }
  431. #endif
  432. else
  433. {
  434. return _genericDictionary[(TKey)key];
  435. }
  436. }
  437. set
  438. {
  439. if (_dictionary != null)
  440. {
  441. _dictionary[key] = value;
  442. }
  443. #if NETSTD
  444. else if (_readOnlyDictionary != null)
  445. {
  446. throw new NotSupportedException();
  447. }
  448. #endif
  449. else
  450. {
  451. _genericDictionary[(TKey)key] = (TValue)value;
  452. }
  453. }
  454. }
  455. private readonly struct DictionaryEnumerator<TEnumeratorKey, TEnumeratorValue> : IDictionaryEnumerator
  456. {
  457. private readonly IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e;
  458. public DictionaryEnumerator(IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e)
  459. {
  460. ValidationUtils.ArgumentNotNull(e, nameof(e));
  461. _e = e;
  462. }
  463. public DictionaryEntry Entry => (DictionaryEntry)Current;
  464. public object Key => Entry.Key;
  465. public object Value => Entry.Value;
  466. public object Current => new DictionaryEntry(_e.Current.Key, _e.Current.Value);
  467. public bool MoveNext()
  468. {
  469. return _e.MoveNext();
  470. }
  471. public void Reset()
  472. {
  473. _e.Reset();
  474. }
  475. }
  476. IDictionaryEnumerator IDictionary.GetEnumerator()
  477. {
  478. if (_dictionary != null)
  479. {
  480. return _dictionary.GetEnumerator();
  481. }
  482. #if NETSTD
  483. else if (_readOnlyDictionary != null)
  484. {
  485. return new DictionaryEnumerator<TKey, TValue>(_readOnlyDictionary.GetEnumerator());
  486. }
  487. #endif
  488. else
  489. {
  490. return new DictionaryEnumerator<TKey, TValue>(_genericDictionary.GetEnumerator());
  491. }
  492. }
  493. bool IDictionary.Contains(object key)
  494. {
  495. if (_genericDictionary != null)
  496. {
  497. return _genericDictionary.ContainsKey((TKey)key);
  498. }
  499. #if NETSTD
  500. else if (_readOnlyDictionary != null)
  501. {
  502. return _readOnlyDictionary.ContainsKey((TKey)key);
  503. }
  504. #endif
  505. else
  506. {
  507. return _dictionary.Contains(key);
  508. }
  509. }
  510. bool IDictionary.IsFixedSize
  511. {
  512. get
  513. {
  514. if (_genericDictionary != null)
  515. {
  516. return false;
  517. }
  518. #if NETSTD
  519. else if (_readOnlyDictionary != null)
  520. {
  521. return true;
  522. }
  523. #endif
  524. else
  525. {
  526. return _dictionary.IsFixedSize;
  527. }
  528. }
  529. }
  530. ICollection IDictionary.Keys
  531. {
  532. get
  533. {
  534. if (_genericDictionary != null)
  535. {
  536. return _genericDictionary.Keys.List();
  537. }
  538. #if NETSTD
  539. else if (_readOnlyDictionary != null)
  540. {
  541. return _readOnlyDictionary.Keys.List();
  542. }
  543. #endif
  544. else
  545. {
  546. return _dictionary.Keys;
  547. }
  548. }
  549. }
  550. public void Remove(object key)
  551. {
  552. if (_dictionary != null)
  553. {
  554. _dictionary.Remove(key);
  555. }
  556. #if NETSTD
  557. else if (_readOnlyDictionary != null)
  558. {
  559. throw new NotSupportedException();
  560. }
  561. #endif
  562. else
  563. {
  564. _genericDictionary.Remove((TKey)key);
  565. }
  566. }
  567. ICollection IDictionary.Values
  568. {
  569. get
  570. {
  571. if (_genericDictionary != null)
  572. {
  573. return _genericDictionary.Values.List();
  574. }
  575. #if NETSTD
  576. else if (_readOnlyDictionary != null)
  577. {
  578. return _readOnlyDictionary.Values.List();
  579. }
  580. #endif
  581. else
  582. {
  583. return _dictionary.Values;
  584. }
  585. }
  586. }
  587. void ICollection.CopyTo(Array array, int index)
  588. {
  589. if (_dictionary != null)
  590. {
  591. _dictionary.CopyTo(array, index);
  592. }
  593. #if NETSTD
  594. else if (_readOnlyDictionary != null)
  595. {
  596. throw new NotSupportedException();
  597. }
  598. #endif
  599. else
  600. {
  601. _genericDictionary.CopyTo((KeyValuePair<TKey, TValue>[])array, index);
  602. }
  603. }
  604. bool ICollection.IsSynchronized
  605. {
  606. get
  607. {
  608. if (_dictionary != null)
  609. {
  610. return _dictionary.IsSynchronized;
  611. }
  612. else
  613. {
  614. return false;
  615. }
  616. }
  617. }
  618. object ICollection.SyncRoot
  619. {
  620. get
  621. {
  622. if (_syncRoot == null)
  623. {
  624. Interlocked.CompareExchange(ref _syncRoot, new object(), null);
  625. }
  626. return _syncRoot;
  627. }
  628. }
  629. public object UnderlyingDictionary
  630. {
  631. get
  632. {
  633. if (_dictionary != null)
  634. {
  635. return _dictionary;
  636. }
  637. #if NETSTD
  638. else if (_readOnlyDictionary != null)
  639. {
  640. return _readOnlyDictionary;
  641. }
  642. #endif
  643. else
  644. {
  645. return _genericDictionary;
  646. }
  647. }
  648. }
  649. }
  650. }