/src/SmartFormat.ZString/repo/src/ZString/StringBuilder.AppendJoin.cs

https://github.com/scottrippey/SmartFormat.NET
C# | 414 lines | 319 code | 45 blank | 50 comment | 32 complexity | dac8cc2d900cf622c88ec7e62cc3deff MD5 | raw file
  1. using System;
  2. using System.Text;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Runtime.CompilerServices;
  7. namespace Cysharp.Text
  8. {
  9. public partial struct Utf16ValueStringBuilder
  10. {
  11. /// <summary>
  12. /// Concatenates the string representations of the elements in the provided array of objects, using the specified char separator between each member, then appends the result to the current instance of the string builder.
  13. /// </summary>
  14. /// <typeparam name="T"></typeparam>
  15. /// <param name="separator"></param>
  16. /// <param name="values"></param>
  17. public void AppendJoin<T>(char separator, params T[] values)
  18. {
  19. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  20. AppendJoinInternal<T>(s, values.AsSpan());
  21. }
  22. public void AppendJoin<T>(char separator, List<T> values)
  23. {
  24. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  25. AppendJoinInternal(s, (IReadOnlyList<T>)values);
  26. }
  27. public void AppendJoin<T>(char separator, ReadOnlySpan<T> values)
  28. {
  29. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  30. AppendJoinInternal(s, values);
  31. }
  32. /// <summary>
  33. /// Concatenates and appends the members of a collection, using the specified char separator between each member.
  34. /// </summary>
  35. /// <typeparam name="T"></typeparam>
  36. /// <param name="separator"></param>
  37. /// <param name="values"></param>
  38. public void AppendJoin<T>(char separator, IEnumerable<T> values)
  39. {
  40. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  41. AppendJoinInternal(s, values);
  42. }
  43. public void AppendJoin<T>(char separator, ICollection<T> values)
  44. {
  45. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  46. AppendJoinInternal(s, values.AsEnumerable());
  47. }
  48. public void AppendJoin<T>(char separator, IList<T> values)
  49. {
  50. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  51. AppendJoinInternal(s, values);
  52. }
  53. public void AppendJoin<T>(char separator, IReadOnlyList<T> values)
  54. {
  55. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  56. AppendJoinInternal(s, values);
  57. }
  58. public void AppendJoin<T>(char separator, IReadOnlyCollection<T> values)
  59. {
  60. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  61. AppendJoinInternal(s, values.AsEnumerable());
  62. }
  63. /// <summary>
  64. /// Concatenates the string representations of the elements in the provided array of objects, using the specified separator between each member, then appends the result to the current instance of the string builder.
  65. /// </summary>
  66. /// <typeparam name="T"></typeparam>
  67. /// <param name="separator"></param>
  68. /// <param name="values"></param>
  69. public void AppendJoin<T>(string separator, params T[] values)
  70. {
  71. AppendJoinInternal<T>(separator.AsSpan(), values.AsSpan());
  72. }
  73. public void AppendJoin<T>(string separator, List<T> values)
  74. {
  75. AppendJoinInternal(separator.AsSpan(), (IReadOnlyList<T>)values);
  76. }
  77. public void AppendJoin<T>(string separator, ReadOnlySpan<T> values)
  78. {
  79. AppendJoinInternal(separator.AsSpan(), values);
  80. }
  81. /// <summary>
  82. /// Concatenates and appends the members of a collection, using the specified separator between each member.
  83. /// </summary>
  84. /// <typeparam name="T"></typeparam>
  85. /// <param name="separator"></param>
  86. /// <param name="values"></param>
  87. public void AppendJoin<T>(string separator, IEnumerable<T> values)
  88. {
  89. AppendJoinInternal(separator.AsSpan(), values);
  90. }
  91. public void AppendJoin<T>(string separator, ICollection<T> values)
  92. {
  93. AppendJoinInternal(separator.AsSpan(), values.AsEnumerable());
  94. }
  95. public void AppendJoin<T>(string separator, IList<T> values)
  96. {
  97. AppendJoinInternal(separator.AsSpan(), values);
  98. }
  99. public void AppendJoin<T>(string separator, IReadOnlyList<T> values)
  100. {
  101. AppendJoinInternal(separator.AsSpan(), values);
  102. }
  103. public void AppendJoin<T>(string separator, IReadOnlyCollection<T> values)
  104. {
  105. AppendJoinInternal(separator.AsSpan(), values.AsEnumerable());
  106. }
  107. internal void AppendJoinInternal<T>(ReadOnlySpan<char> separator, IList<T> values)
  108. {
  109. var readOnlyList = values as IReadOnlyList<T>;
  110. // Boxing will occur, but JIT will be de-virtualized.
  111. readOnlyList = readOnlyList ?? new ReadOnlyListAdaptor<T>(values);
  112. AppendJoinInternal(separator, readOnlyList);
  113. }
  114. internal void AppendJoinInternal<T>(ReadOnlySpan<char> separator, IReadOnlyList<T> values)
  115. {
  116. var count = values.Count;
  117. for (int i = 0; i < count; i++)
  118. {
  119. if (i != 0)
  120. {
  121. Append(separator);
  122. }
  123. var item = values[i];
  124. if (typeof(T) == typeof(string))
  125. {
  126. var s = Unsafe.As<string>(item);
  127. if (!string.IsNullOrEmpty(s))
  128. {
  129. Append(s);
  130. }
  131. }
  132. else
  133. {
  134. Append(item);
  135. }
  136. }
  137. }
  138. internal void AppendJoinInternal<T>(ReadOnlySpan<char> separator, ReadOnlySpan<T> values)
  139. {
  140. for (int i = 0; i < values.Length; i++)
  141. {
  142. if (i != 0)
  143. {
  144. Append(separator);
  145. }
  146. var item = values[i];
  147. if (typeof(T) == typeof(string))
  148. {
  149. var s = Unsafe.As<string>(item);
  150. if (!string.IsNullOrEmpty(s))
  151. {
  152. Append(s);
  153. }
  154. }
  155. else
  156. {
  157. Append(item);
  158. }
  159. }
  160. }
  161. internal void AppendJoinInternal<T>(ReadOnlySpan<char> separator, IEnumerable<T> values)
  162. {
  163. var isFirst = true;
  164. foreach (var item in values)
  165. {
  166. if (!isFirst)
  167. {
  168. Append(separator);
  169. }
  170. else
  171. {
  172. isFirst = false;
  173. }
  174. if (typeof(T) == typeof(string))
  175. {
  176. var s = Unsafe.As<string>(item);
  177. if (!string.IsNullOrEmpty(s))
  178. {
  179. Append(s);
  180. }
  181. }
  182. else
  183. {
  184. Append(item);
  185. }
  186. }
  187. }
  188. }
  189. public partial struct Utf8ValueStringBuilder
  190. {
  191. /// <summary>
  192. /// Concatenates the string representations of the elements in the provided array of objects, using the specified char separator between each member, then appends the result to the current instance of the string builder.
  193. /// </summary>
  194. /// <typeparam name="T"></typeparam>
  195. /// <param name="separator"></param>
  196. /// <param name="values"></param>
  197. public void AppendJoin<T>(char separator, params T[] values)
  198. {
  199. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  200. AppendJoinInternal<T>(s, values.AsSpan());
  201. }
  202. public void AppendJoin<T>(char separator, List<T> values)
  203. {
  204. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  205. AppendJoinInternal(s, (IReadOnlyList<T>)values);
  206. }
  207. public void AppendJoin<T>(char separator, ReadOnlySpan<T> values)
  208. {
  209. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  210. AppendJoinInternal(s, values);
  211. }
  212. /// <summary>
  213. /// Concatenates and appends the members of a collection, using the specified char separator between each member.
  214. /// </summary>
  215. /// <typeparam name="T"></typeparam>
  216. /// <param name="separator"></param>
  217. /// <param name="values"></param>
  218. public void AppendJoin<T>(char separator, IEnumerable<T> values)
  219. {
  220. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  221. AppendJoinInternal(s, values);
  222. }
  223. public void AppendJoin<T>(char separator, ICollection<T> values)
  224. {
  225. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  226. AppendJoinInternal(s, values.AsEnumerable());
  227. }
  228. public void AppendJoin<T>(char separator, IList<T> values)
  229. {
  230. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  231. AppendJoinInternal(s, values);
  232. }
  233. public void AppendJoin<T>(char separator, IReadOnlyList<T> values)
  234. {
  235. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  236. AppendJoinInternal(s, values);
  237. }
  238. public void AppendJoin<T>(char separator, IReadOnlyCollection<T> values)
  239. {
  240. ReadOnlySpan<char> s = stackalloc char[1] { separator };
  241. AppendJoinInternal(s, values.AsEnumerable());
  242. }
  243. /// <summary>
  244. /// Concatenates the string representations of the elements in the provided array of objects, using the specified separator between each member, then appends the result to the current instance of the string builder.
  245. /// </summary>
  246. /// <typeparam name="T"></typeparam>
  247. /// <param name="separator"></param>
  248. /// <param name="values"></param>
  249. public void AppendJoin<T>(string separator, params T[] values)
  250. {
  251. AppendJoinInternal<T>(separator.AsSpan(), values.AsSpan());
  252. }
  253. public void AppendJoin<T>(string separator, List<T> values)
  254. {
  255. AppendJoinInternal(separator.AsSpan(), (IReadOnlyList<T>)values);
  256. }
  257. public void AppendJoin<T>(string separator, ReadOnlySpan<T> values)
  258. {
  259. AppendJoinInternal(separator.AsSpan(), values);
  260. }
  261. /// <summary>
  262. /// Concatenates and appends the members of a collection, using the specified separator between each member.
  263. /// </summary>
  264. /// <typeparam name="T"></typeparam>
  265. /// <param name="separator"></param>
  266. /// <param name="values"></param>
  267. public void AppendJoin<T>(string separator, IEnumerable<T> values)
  268. {
  269. AppendJoinInternal(separator.AsSpan(), values);
  270. }
  271. public void AppendJoin<T>(string separator, ICollection<T> values)
  272. {
  273. AppendJoinInternal(separator.AsSpan(), values.AsEnumerable());
  274. }
  275. public void AppendJoin<T>(string separator, IList<T> values)
  276. {
  277. AppendJoinInternal(separator.AsSpan(), values);
  278. }
  279. public void AppendJoin<T>(string separator, IReadOnlyList<T> values)
  280. {
  281. AppendJoinInternal(separator.AsSpan(), values);
  282. }
  283. public void AppendJoin<T>(string separator, IReadOnlyCollection<T> values)
  284. {
  285. AppendJoinInternal(separator.AsSpan(), values.AsEnumerable());
  286. }
  287. internal void AppendJoinInternal<T>(ReadOnlySpan<char> separator, IList<T> values)
  288. {
  289. var readOnlyList = values as IReadOnlyList<T>;
  290. // Boxing will occur, but JIT will be de-virtualized.
  291. readOnlyList = readOnlyList ?? new ReadOnlyListAdaptor<T>(values);
  292. AppendJoinInternal(separator, readOnlyList);
  293. }
  294. internal void AppendJoinInternal<T>(ReadOnlySpan<char> separator, IReadOnlyList<T> values)
  295. {
  296. var count = values.Count;
  297. for (int i = 0; i < count; i++)
  298. {
  299. if (i != 0)
  300. {
  301. Append(separator);
  302. }
  303. var item = values[i];
  304. if (typeof(T) == typeof(string))
  305. {
  306. var s = Unsafe.As<string>(item);
  307. if (!string.IsNullOrEmpty(s))
  308. {
  309. Append(s);
  310. }
  311. }
  312. else
  313. {
  314. Append(item);
  315. }
  316. }
  317. }
  318. internal void AppendJoinInternal<T>(ReadOnlySpan<char> separator, ReadOnlySpan<T> values)
  319. {
  320. for (int i = 0; i < values.Length; i++)
  321. {
  322. if (i != 0)
  323. {
  324. Append(separator);
  325. }
  326. var item = values[i];
  327. if (typeof(T) == typeof(string))
  328. {
  329. var s = Unsafe.As<string>(item);
  330. if (!string.IsNullOrEmpty(s))
  331. {
  332. Append(s);
  333. }
  334. }
  335. else
  336. {
  337. Append(item);
  338. }
  339. }
  340. }
  341. internal void AppendJoinInternal<T>(ReadOnlySpan<char> separator, IEnumerable<T> values)
  342. {
  343. var isFirst = true;
  344. foreach (var item in values)
  345. {
  346. if (!isFirst)
  347. {
  348. Append(separator);
  349. }
  350. else
  351. {
  352. isFirst = false;
  353. }
  354. if (typeof(T) == typeof(string))
  355. {
  356. var s = Unsafe.As<string>(item);
  357. if (!string.IsNullOrEmpty(s))
  358. {
  359. Append(s);
  360. }
  361. }
  362. else
  363. {
  364. Append(item);
  365. }
  366. }
  367. }
  368. }
  369. }