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.

246 lines
14 KiB

  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. #if HAVE_ASYNC
  26. using System;
  27. using System.Collections.Generic;
  28. using System.Threading;
  29. using System.Threading.Tasks;
  30. using Newtonsoft.Json.Utilities;
  31. namespace Newtonsoft.Json
  32. {
  33. internal abstract partial class JsonReader
  34. {
  35. /// <summary>
  36. /// Asynchronously reads the next JSON token from the source.
  37. /// </summary>
  38. /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
  39. /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous read. The <see cref="Task{TResult}.Result"/>
  40. /// property returns <c>true</c> if the next token was read successfully; <c>false</c> if there are no more tokens to read.</returns>
  41. /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
  42. /// classes can override this behaviour for true asynchronicity.</remarks>
  43. public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken))
  44. {
  45. return cancellationToken.CancelIfRequestedAsync<bool>() ?? Read().ToAsync();
  46. }
  47. /// <summary>
  48. /// Asynchronously skips the children of the current token.
  49. /// </summary>
  50. /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
  51. /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
  52. /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
  53. /// classes can override this behaviour for true asynchronicity.</remarks>
  54. public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken))
  55. {
  56. if (TokenType == JsonToken.PropertyName)
  57. {
  58. await ReadAsync(cancellationToken).ConfigureAwait(false);
  59. }
  60. if (JsonTokenUtils.IsStartToken(TokenType))
  61. {
  62. int depth = Depth;
  63. while (await ReadAsync(cancellationToken).ConfigureAwait(false) && depth < Depth)
  64. {
  65. }
  66. }
  67. }
  68. internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken)
  69. {
  70. if (!await ReadAsync(cancellationToken).ConfigureAwait(false))
  71. {
  72. throw CreateUnexpectedEndException();
  73. }
  74. }
  75. /// <summary>
  76. /// Asynchronously reads the next JSON token from the source as a <see cref="Nullable{T}"/> of <see cref="bool"/>.
  77. /// </summary>
  78. /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
  79. /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous read. The <see cref="Task{TResult}.Result"/>
  80. /// property returns the <see cref="Nullable{T}"/> of <see cref="bool"/>. This result will be <c>null</c> at the end of an array.</returns>
  81. /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
  82. /// classes can override this behaviour for true asynchronicity.</remarks>
  83. public virtual Task<bool?> ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken))
  84. {
  85. return cancellationToken.CancelIfRequestedAsync<bool?>() ?? Task.FromResult(ReadAsBoolean());
  86. }
  87. /// <summary>
  88. /// Asynchronously reads the next JSON token from the source as a <see cref="byte"/>[].
  89. /// </summary>
  90. /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
  91. /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous read. The <see cref="Task{TResult}.Result"/>
  92. /// property returns the <see cref="byte"/>[]. This result will be <c>null</c> at the end of an array.</returns>
  93. /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
  94. /// classes can override this behaviour for true asynchronicity.</remarks>
  95. public virtual Task<byte[]> ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken))
  96. {
  97. return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes());
  98. }
  99. internal async Task<byte[]> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken)
  100. {
  101. List<byte> buffer = new List<byte>();
  102. while (true)
  103. {
  104. if (!await ReadAsync(cancellationToken).ConfigureAwait(false))
  105. {
  106. SetToken(JsonToken.None);
  107. }
  108. if (ReadArrayElementIntoByteArrayReportDone(buffer))
  109. {
  110. byte[] d = buffer.ToArray();
  111. SetToken(JsonToken.Bytes, d, false);
  112. return d;
  113. }
  114. }
  115. }
  116. /// <summary>
  117. /// Asynchronously reads the next JSON token from the source as a <see cref="Nullable{T}"/> of <see cref="DateTime"/>.
  118. /// </summary>
  119. /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
  120. /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous read. The <see cref="Task{TResult}.Result"/>
  121. /// property returns the <see cref="Nullable{T}"/> of <see cref="DateTime"/>. This result will be <c>null</c> at the end of an array.</returns>
  122. /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
  123. /// classes can override this behaviour for true asynchronicity.</remarks>
  124. public virtual Task<DateTime?> ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken))
  125. {
  126. return cancellationToken.CancelIfRequestedAsync<DateTime?>() ?? Task.FromResult(ReadAsDateTime());
  127. }
  128. /// <summary>
  129. /// Asynchronously reads the next JSON token from the source as a <see cref="Nullable{T}"/> of <see cref="DateTimeOffset"/>.
  130. /// </summary>
  131. /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
  132. /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous read. The <see cref="Task{TResult}.Result"/>
  133. /// property returns the <see cref="Nullable{T}"/> of <see cref="DateTimeOffset"/>. This result will be <c>null</c> at the end of an array.</returns>
  134. /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
  135. /// classes can override this behaviour for true asynchronicity.</remarks>
  136. public virtual Task<DateTimeOffset?> ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken))
  137. {
  138. return cancellationToken.CancelIfRequestedAsync<DateTimeOffset?>() ?? Task.FromResult(ReadAsDateTimeOffset());
  139. }
  140. /// <summary>
  141. /// Asynchronously reads the next JSON token from the source as a <see cref="Nullable{T}"/> of <see cref="decimal"/>.
  142. /// </summary>
  143. /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
  144. /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous read. The <see cref="Task{TResult}.Result"/>
  145. /// property returns the <see cref="Nullable{T}"/> of <see cref="decimal"/>. This result will be <c>null</c> at the end of an array.</returns>
  146. /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
  147. /// classes can override this behaviour for true asynchronicity.</remarks>
  148. public virtual Task<decimal?> ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken))
  149. {
  150. return cancellationToken.CancelIfRequestedAsync<decimal?>() ?? Task.FromResult(ReadAsDecimal());
  151. }
  152. /// <summary>
  153. /// Asynchronously reads the next JSON token from the source as a <see cref="Nullable{T}"/> of <see cref="double"/>.
  154. /// </summary>
  155. /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
  156. /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous read. The <see cref="Task{TResult}.Result"/>
  157. /// property returns the <see cref="Nullable{T}"/> of <see cref="double"/>. This result will be <c>null</c> at the end of an array.</returns>
  158. /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
  159. /// classes can override this behaviour for true asynchronicity.</remarks>
  160. public virtual Task<double?> ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken))
  161. {
  162. return Task.FromResult(ReadAsDouble());
  163. }
  164. /// <summary>
  165. /// Asynchronously reads the next JSON token from the source as a <see cref="Nullable{T}"/> of <see cref="int"/>.
  166. /// </summary>
  167. /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
  168. /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous read. The <see cref="Task{TResult}.Result"/>
  169. /// property returns the <see cref="Nullable{T}"/> of <see cref="int"/>. This result will be <c>null</c> at the end of an array.</returns>
  170. /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
  171. /// classes can override this behaviour for true asynchronicity.</remarks>
  172. public virtual Task<int?> ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken))
  173. {
  174. return cancellationToken.CancelIfRequestedAsync<int?>() ?? Task.FromResult(ReadAsInt32());
  175. }
  176. /// <summary>
  177. /// Asynchronously reads the next JSON token from the source as a <see cref="string"/>.
  178. /// </summary>
  179. /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
  180. /// <returns>A <see cref="Task{TResult}"/> that represents the asynchronous read. The <see cref="Task{TResult}.Result"/>
  181. /// property returns the <see cref="string"/>. This result will be <c>null</c> at the end of an array.</returns>
  182. /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
  183. /// classes can override this behaviour for true asynchronicity.</remarks>
  184. public virtual Task<string> ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken))
  185. {
  186. return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString());
  187. }
  188. internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken)
  189. {
  190. return await ReadAsync(cancellationToken).ConfigureAwait(false) && await MoveToContentAsync(cancellationToken).ConfigureAwait(false);
  191. }
  192. internal Task<bool> MoveToContentAsync(CancellationToken cancellationToken)
  193. {
  194. switch (TokenType)
  195. {
  196. case JsonToken.None:
  197. case JsonToken.Comment:
  198. return MoveToContentFromNonContentAsync(cancellationToken);
  199. default:
  200. return AsyncUtils.True;
  201. }
  202. }
  203. private async Task<bool> MoveToContentFromNonContentAsync(CancellationToken cancellationToken)
  204. {
  205. while (true)
  206. {
  207. if (!await ReadAsync(cancellationToken).ConfigureAwait(false))
  208. {
  209. return false;
  210. }
  211. switch (TokenType)
  212. {
  213. case JsonToken.None:
  214. case JsonToken.Comment:
  215. break;
  216. default:
  217. return true;
  218. }
  219. }
  220. }
  221. }
  222. }
  223. #endif