CodePorting.Translator Cs2Cpp
CodePorting.Translator.Cs2Cpp.Framework
memory_extensions.h
1
2#ifndef _aspose_system_memory_extensions_h_
3#define _aspose_system_memory_extensions_h_
4
5#include <type_traits>
6#include <array>
7#include <system/array_segment.h>
8#include <system/span.h>
9#include <system/memory.h>
10#include <system/object.h>
11#include <system/object_ext.h>
12#include <system/details/stack_array.h>
13#include <system/smart_ptr.h>
14#include <system/exceptions.h>
15#include <system/comparison.h>
16#include <system/range.h>
17
18namespace System {
19
21namespace MemoryExtensions {
22namespace Details {
24extern ASPOSECPP_SHARED_API const std::array<char16_t, 22> DefaultWhitespaceChars;
25
27extern ASPOSECPP_SHARED_API const ReadOnlySpan<char16_t> DefaultWhitespaceSpan;
28
35template <typename T, typename U>
36int32_t Compare(const SharedPtr<T>& a, const SharedPtr<U>& b);
37
43template <typename T>
44int32_t // typename std::enable_if<std::is_arithmetic<T>::value, int32_t>::type
45 Compare(const T& a, const T& b);
46
53template <typename T, typename U>
54int32_t Compare(const SharedPtr<T>& a, const U& b);
55
56
63template <typename T>
64int32_t LastIndexOfImpl(const ReadOnlySpan<T>& searchSpace, int32_t length, const T& value);
65
66
74template <typename T>
75bool SequenceEqualImpl(const ReadOnlySpan<T>& first, const int32_t start, int32_t length, const ReadOnlySpan<T>& second);
76
84template <typename TKey, typename TValue>
85void IntroSort(Span<TKey>& keys, Span<TValue>& values, int32_t depthLimit,
86 std::function<int32_t(const TKey&, const TKey&)> comparer);
87
96template <typename TKey, typename TValue>
98 std::function<int32_t(const TKey&, const TKey&)> comparer, int32_t i, int32_t j);
99
106template <typename TKey, typename TValue>
107void InsertionSort(Span<TKey>& keys, Span<TValue>& values, std::function<int32_t(const TKey&, const TKey&)> comparer);
108
115template <typename TKey, typename TValue>
116void HeapSort(Span<TKey>& keys, Span<TValue>& values, std::function<int32_t(const TKey&, const TKey&)> comparer);
117
126template <typename TKey, typename TValue>
127void Heapify(Span<TKey>& keys, Span<TValue>& values, int32_t n, int32_t i,
128 std::function<int32_t(const TKey&, const TKey&)> comparer);
129
137template <typename TKey, typename TValue>
138int32_t PickPivotAndPartition(Span<TKey>& keys, Span<TValue>& values,
139 std::function<int32_t(const TKey&, const TKey&)> comparer);
140
149template <typename T, typename TValue, typename TCompareFunc>
150int32_t BinarySearchImpl(const ReadOnlySpan<T>& span, const TValue& value, TCompareFunc compareFunc);
151
152template <typename T, typename U>
153int32_t Compare(const SharedPtr<T>& a, const SharedPtr<U>& b)
154{
155 if (!a && !b)
156 {
157 return 0;
158 }
159 if (!a)
160 {
161 return -1;
162 }
163 if (!b)
164 {
165 return 1;
166 }
167 // assume T implements IComparable<Ptr<U>>
168 return (*a).CompareTo(b);
169}
170
171template <typename T>
172int32_t // typename std::enable_if<std::is_arithmetic<T>::value, int32_t>::type
173 Compare(const T& a, const T& b)
174{
175 return System::Compare(a, b);
176}
177
178template <typename T, typename U>
179int32_t Compare(const SharedPtr<T>& a, const U& b)
180{
181 // assume T implements IComparable<U>
182 return (*a).CompareTo(b);
183}
184
185template <typename T>
186int32_t LastIndexOfImpl(const ReadOnlySpan<T>& searchSpace, int32_t length, const T& value)
187{
188 // TODO if value is null find null
189 if (length < 0)
190 return -1;
191
192 while (length >= 8)
193 {
194 length -= 8;
195 if (System::ObjectExt::Equals(value, searchSpace.get(length + 7)))
196 return length + 7;
197 if (System::ObjectExt::Equals(value, searchSpace.get(length + 6)))
198 return length + 6;
199 if (System::ObjectExt::Equals(value, searchSpace.get(length + 5)))
200 return length + 5;
201 if (System::ObjectExt::Equals(value, searchSpace.get(length + 4)))
202 return length + 4;
203 if (System::ObjectExt::Equals(value, searchSpace.get(length + 3)))
204 return length + 3;
205 if (System::ObjectExt::Equals(value, searchSpace.get(length + 2)))
206 return length + 2;
207 if (System::ObjectExt::Equals(value, searchSpace.get(length + 1)))
208 return length + 1;
209 if (System::ObjectExt::Equals(value, searchSpace.get(length)))
210 return length;
211 }
212
213 while (length > 0)
214 {
215 length--;
216 if (System::ObjectExt::Equals(value, searchSpace.get(length)))
217 {
218 return length;
219 }
220 }
221
222 return -1;
223}
224
225template <typename T>
226bool SequenceEqualImpl(const ReadOnlySpan<T>& first, const int32_t start, int32_t length, const ReadOnlySpan<T>& second)
227{
228 int32_t index = 0;
229
230 // Process 8 elements at a time
231 while (length >= 8)
232 {
233 if (!(System::ObjectExt::Equals(first.get(index + start), second.get(index))) ||
234 !(System::ObjectExt::Equals(first.get(index + start + 1), second.get(index + 1))) ||
235 !(System::ObjectExt::Equals(first.get(index + start + 2), second.get(index + 2))) ||
236 !(System::ObjectExt::Equals(first.get(index + start + 3), second.get(index + 3))) ||
237 !(System::ObjectExt::Equals(first.get(index + start + 4), second.get(index + 4))) ||
238 !(System::ObjectExt::Equals(first.get(index + start + 5), second.get(index + 5))) ||
239 !(System::ObjectExt::Equals(first.get(index + start + 6), second.get(index + 6))) ||
240 !(System::ObjectExt::Equals(first.get(index + start + 7), second.get(index + 7))))
241 {
242 return false;
243 }
244
245 index += 8;
246 length -= 8;
247 }
248
249 // Process remaining elements one by one
250 while (length > 0)
251 {
252 if (!(System::ObjectExt::Equals(first.get(index + start), second.get(index))))
253 {
254 return false;
255 }
256 index++;
257 length--;
258 }
259 return true;
260}
261
262template <typename TKey, typename TValue>
263void IntroSort(Span<TKey>& keys, Span<TValue>& values, int32_t depthLimit,
264 std::function<int32_t(const TKey&, const TKey&)> comparer)
265{
266 int32_t partitionSize = keys.get_Length();
267 while (partitionSize > 1)
268 {
269 if (partitionSize <= 16)
270 { // IntrosortSizeThreshold = 16
271 if (partitionSize == 2)
272 {
273 SwapIfGreaterWithValues(keys, values, comparer, 0, 1);
274 return;
275 }
276
277 if (partitionSize == 3)
278 {
279 SwapIfGreaterWithValues(keys, values, comparer, 0, 1);
280 SwapIfGreaterWithValues(keys, values, comparer, 0, 2);
281 SwapIfGreaterWithValues(keys, values, comparer, 1, 2);
282 return;
283 }
284
285 InsertionSort(keys, values, comparer);
286 return;
287 }
288
289 if (depthLimit == 0)
290 {
291 HeapSort(keys, values, comparer);
292 return;
293 }
294 depthLimit--;
295
296 int32_t p = PickPivotAndPartition(keys, values, comparer);
297
298 // Handle the case where pivot is at the end
299 int32_t rightSize = partitionSize - p - 1;
300 if (rightSize > 0)
301 {
302 IntroSort(keys.Slice(p + 1, rightSize), values.Slice(p + 1, rightSize), depthLimit, comparer);
303 }
304
305 // Handle the case where pivot is at the beginning
306 partitionSize = p;
307 }
308}
309
310template <typename TKey, typename TValue>
312 std::function<int32_t(const TKey&, const TKey&)> comparer, int32_t i, int32_t j)
313{
314 if (comparer(keys.get(i), keys.get(j)) > 0)
315 {
316 std::swap(keys.get(i), keys.get(j));
317 std::swap(values.get(i), values.get(j));
318 }
319}
320
321template <typename TKey, typename TValue>
322void InsertionSort(Span<TKey>& keys, Span<TValue>& values, std::function<int32_t(const TKey&, const TKey&)> comparer)
323{
324 for (int32_t i = 0; i < keys.get_Length() - 1; i++)
325 {
326 TKey t = keys.get(i + 1);
327 TValue tValue = values.get(i + 1);
328
329 int32_t j = i;
330 while (j >= 0 && keys.get(j) != t && !comparer(t, keys.get(j)))
331 {
332 keys.get(j + 1) = keys.get(j);
333 values.get(j + 1) = values.get(j);
334 j--;
335 }
336
337 keys.get(j + 1) = t;
338 values.get(j + 1) = tValue;
339 }
340}
341
342template <typename TKey, typename TValue>
343void HeapSort(Span<TKey>& keys, Span<TValue>& values, std::function<int32_t(const TKey&, const TKey&)> comparer)
344{
345 // Build max heap
346 for (int32_t i = keys.get_Length() / 2 - 1; i >= 0; i--)
347 {
348 Heapify(keys, values, keys.get_Length(), i, comparer);
349 }
350
351 // Extract elements from heap one by one
352 for (int32_t i = keys.get_Length() - 1; i > 0; i--)
353 {
354 std::swap(keys.get(0), keys.get(i));
355 std::swap(values.get(0), values.get(i));
356 Heapify(keys, values, i, 0, comparer);
357 }
358}
359
360
361template <typename TKey, typename TValue>
362void Heapify(Span<TKey>& keys, Span<TValue>& values, int32_t n, int32_t i,
363 std::function<int32_t(const TKey&, const TKey&)> comparer)
364{
365 int32_t largest = i;
366 int32_t left = 2 * i + 1;
367 int32_t right = 2 * i + 2;
368
369 if (left < n && comparer(keys.get(left), keys.get(largest)) > 0)
370 {
371 largest = left;
372 }
373
374 if (right < n && comparer(keys.get(right), keys.get(largest)) > 0)
375 {
376 largest = right;
377 }
378
379 if (largest != i)
380 {
381 std::swap(keys.get(i), keys.get(largest));
382 std::swap(values.get(i), values.get(largest));
383 Heapify(keys, values, n, largest, comparer);
384 }
385}
386
387template <typename TKey, typename TValue>
389 std::function<int32_t(const TKey&, const TKey&)> comparer)
390{
391 // Use median-of-three pivot selection
392 int32_t middle = keys.get_Length() / 2;
393 int32_t last = keys.get_Length() - 1;
394
395 // Sort first, middle, last
396 if (comparer(keys.get(0), keys.get(middle)) > 0)
397 {
398 std::swap(keys.get(0), keys.get(middle));
399 std::swap(values.get(0), values.get(middle));
400 }
401 if (comparer(keys.get(0), keys.get(last)) > 0)
402 {
403 std::swap(keys.get(0), keys.get(last));
404 std::swap(values.get(0), values.get(last));
405 }
406 if (comparer(keys.get(middle), keys.get(last)) > 0)
407 {
408 std::swap(keys.get(middle), keys.get(last));
409 std::swap(values.get(middle), values.get(last));
410 }
411
412 // Place pivot at last position
413 std::swap(keys.get(middle), keys.get(last));
414 std::swap(values.get(middle), values.get(last));
415
416 TKey pivot = keys.get(last);
417 int32_t i = -1;
418
419 for (int32_t j = 0; j < last; j++)
420 {
421 if (comparer(keys.get(j), pivot) <= 0)
422 {
423 i++;
424 std::swap(keys.get(i), keys.get(j));
425 std::swap(values.get(i), values.get(j));
426 }
427 }
428
429 std::swap(keys.get(i + 1), keys.get(last));
430 std::swap(values.get(i + 1), values.get(last));
431 return i + 1;
432}
433
434template <typename T, typename TValue, typename TCompareFunc>
435int32_t BinarySearchImpl(const ReadOnlySpan<T>& span, const TValue& value, TCompareFunc compareFunc)
436{
437 int32_t lo = 0;
438 int32_t hi = span.get_Length() - 1;
439
440 while (lo <= hi)
441 {
442 // Safe unsigned arithmetic to avoid overflow
443 int32_t i = static_cast<int32_t>((static_cast<uint32_t>(hi) + static_cast<uint32_t>(lo)) >> 1);
444 int32_t c = compareFunc(value, span.get(i));
445 if (c == 0)
446 {
447 return i;
448 }
449 else if (c > 0)
450 {
451 lo = i + 1;
452 }
453 else
454 {
455 hi = i - 1;
456 }
457 }
458
459 return ~lo;
460}
461
462} // namespace Details
463
468ASPOSECPP_SHARED_API ReadOnlyMemory<char16_t> AsMemory(const System::String& text);
469
474ASPOSECPP_SHARED_API ReadOnlyMemory<char16_t> AsMemory(const System::String& text, int32_t start);
475
481ASPOSECPP_SHARED_API ReadOnlyMemory<char16_t> AsMemory(const System::String& text, int32_t start, int32_t length);
482
487template <typename T>
488Memory<T> AsMemory(const ArrayPtr<T>& array);
489
495template <typename T>
496Memory<T> AsMemory(const ArrayPtr<T>& array, int32_t start);
497
504template <typename T>
505Memory<T> AsMemory(const ArrayPtr<T>& array, int32_t start, int32_t length);
506
511template <typename T>
512Memory<T> AsMemory(const ArraySegment<T>& segment);
513
519template <typename T>
520Memory<T> AsMemory(const ArrayPtr<T>& array, const Range& range);
521
528template <typename T>
529Span<T> AsSpan(const ArrayPtr<T>& array, int32_t start = 0, int32_t length = -1);
530
537template <typename T, typename TComparable>
538int32_t BinarySearch(const ReadOnlySpan<T>& span, const TComparable& comparable);
539
547template <typename T, typename TComparer>
548int32_t BinarySearch(const ReadOnlySpan<T>& span, const T& value, const SharedPtr<TComparer>& comparerPtr);
549
556template <typename T, typename TComparable>
557int32_t BinarySearch(const Span<T>& span, const TComparable& comparable);
558
566template <typename T, typename TComparer>
567int32_t BinarySearch(const Span<T>& span, const T& value, const SharedPtr<TComparer>& comparer);
568
574template <typename T>
575int32_t CommonPrefixLength(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other);
576
582template <typename T>
583int32_t CommonPrefixLength(const Span<T>& span, const ReadOnlySpan<T>& other);
584
590template <typename T>
591int32_t CommonPrefixLength(const Span<T>& span, const Span<T>& other);
592
600template <typename T, typename TEqualityComparer>
601int32_t CommonPrefixLength(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other,
602 const SharedPtr<TEqualityComparer>& comparer);
603
612template <typename T, typename TEqualityComparer>
613int32_t CommonPrefixLength(const Span<T>& span, const ReadOnlySpan<T>& other,
614 const SharedPtr<TEqualityComparer>& comparer);
615
616
624template <typename T, typename TEqualityComparer>
625int32_t CommonPrefixLength(const Span<T>& span, const Span<T>& other, const SharedPtr<TEqualityComparer>& comparer);
626
627
633template <typename T>
634bool Contains(const ReadOnlySpan<T>& span, const T& value);
635
636
642template <typename T>
643bool Contains(const Span<T>& span, const T& value);
644
645
652template <typename T>
653bool ContainsAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1);
654
655
663template <typename T>
664bool ContainsAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2);
665
666
673template <typename T>
674bool ContainsAny(const Span<T>& span, const T& value0, const T& value1);
675
676
684template <typename T>
685bool ContainsAny(const Span<T>& span, const T& value0, const T& value1, const T& value2);
686
687
693template <typename T>
694bool ContainsAny(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values);
695
696
702template <typename T>
703bool ContainsAny(const Span<T>& span, const ReadOnlySpan<T>& values);
704
705
713template <typename T>
714bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2);
715
716
724template <typename T>
725bool ContainsAnyExcept(const Span<T>& span, const T& value0, const T& value1, const T& value2);
726
727
734template <typename T>
735bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1);
736
737
744template <typename T>
745bool ContainsAnyExcept(const Span<T>& span, const T& value0, const T& value1);
746
747
753template <typename T>
754bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const T& value);
755
756
762template <typename T>
763bool ContainsAnyExcept(const Span<T>& span, const T& value);
764
765
771template <typename T>
772bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values);
773
774
780template <typename T>
781bool ContainsAnyExcept(const Span<T>& span, const ReadOnlySpan<T>& values);
782
783
790template <typename T>
791bool ContainsAnyExceptInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive);
792
793
800template <typename T>
801bool ContainsAnyExceptInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive);
802
803
810template <typename T>
811bool ContainsAnyInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive);
812
813
820template <typename T>
821bool ContainsAnyInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive);
822
823
828template <typename T>
829void CopyTo(const ArrayPtr<T>& source, Span<T>& destination);
830
831
837template <typename T>
838int32_t Count(const ReadOnlySpan<T>& span, const T& value);
839
840
846template <typename T>
847int32_t Count(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value);
848
849
855template <typename T>
856int32_t Count(const Span<T>& span, const T& value);
857
858
864template <typename T>
865int32_t Count(const Span<T>& span, const ReadOnlySpan<T>& value);
866
867
873template <typename T>
874bool EndsWith(const ReadOnlySpan<T>& span, const T& value);
875
876
882template <typename T>
883bool EndsWith(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value);
884
885
891template <typename T>
892bool EndsWith(const Span<T>& span, const ReadOnlySpan<T>& value);
893
894
900template <typename T>
901bool EndsWith(const ReadOnlySpan<T>& span, const Span<T>& value);
902
903
909template <typename T>
910bool EndsWith(const Span<T>& span, const Span<T>& value);
911
912
918template <typename T>
919int32_t IndexOf(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value);
920
921
927template <typename T>
928int32_t IndexOf(const ReadOnlySpan<T>& span, const T& value);
929
930
936template <typename T>
937int32_t IndexOf(const Span<T>& span, const ReadOnlySpan<T>& value);
938
939
945template <typename T>
946int32_t IndexOf(const Span<T>& span, const T& value);
947
948
955template <typename T>
956int32_t IndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1);
957
958
966template <typename T>
967int32_t IndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2);
968
969
976template <typename T>
977int32_t IndexOfAny(const Span<T>& span, const T& value0, const T& value1);
978
979
987template <typename T>
988int32_t IndexOfAny(const Span<T>& span, const T& value0, const T& value1, const T& value2);
989
990
996template <typename T>
997int32_t IndexOfAny(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values);
998
999
1005template <typename T>
1006int32_t IndexOfAny(const Span<T>& span, const ReadOnlySpan<T>& values);
1007
1008
1014template <typename T>
1015int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value);
1016
1017
1025template <typename T>
1026int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1);
1027
1028
1037template <typename T>
1038int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2);
1039
1040
1046template <typename T>
1047int32_t IndexOfAnyExcept(const Span<T>& span, const T& value);
1048
1049
1056template <typename T>
1057int32_t IndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1);
1058
1059
1067template <typename T>
1068int32_t IndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1, const T& value2);
1069
1070
1076template <typename T>
1077int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values);
1078
1079
1085template <typename T>
1086int32_t IndexOfAnyExcept(const Span<T>& span, const ReadOnlySpan<T>& values);
1087
1088
1095template <typename T>
1096int32_t IndexOfAnyExceptInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive);
1097
1098
1105template <typename T>
1106int32_t IndexOfAnyExceptInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive);
1107
1108
1115template <typename T>
1116int32_t IndexOfAnyInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive);
1117
1118
1125template <typename T>
1126int32_t IndexOfAnyInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive);
1127
1128
1134template <typename T>
1135int32_t LastIndexOf(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value);
1136
1137
1143template <typename T>
1144int32_t LastIndexOf(const ReadOnlySpan<T>& span, const T& value);
1145
1146
1152template <typename T>
1153int32_t LastIndexOf(const Span<T>& span, const ReadOnlySpan<T>& value);
1154
1155
1161template <typename T>
1162int32_t LastIndexOf(const Span<T>& span, const T& value);
1163
1164
1172template <typename T>
1173int32_t LastIndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2);
1174
1175
1183template <typename T>
1184int32_t LastIndexOfAny(const Span<T>& span, const T& value0, const T& value1, const T& value2);
1185
1186
1193template <typename T>
1194int32_t LastIndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1);
1195
1196
1203template <typename T>
1204int32_t LastIndexOfAny(const Span<T>& span, const T& value0, const T& value1);
1205
1206
1212template <typename T>
1213int32_t LastIndexOfAny(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values);
1214
1215
1221template <typename T>
1222int32_t LastIndexOfAny(const Span<T>& span, const ReadOnlySpan<T>& values);
1223
1224
1230template <typename T>
1231int32_t LastIndexOfAny(const Span<T>& span, const Span<T>& values);
1232
1233
1241template <typename T>
1242int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2);
1243
1244
1252template <typename T>
1253int32_t LastIndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1, const T& value2);
1254
1255
1262template <typename T>
1263int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1);
1264
1265
1272template <typename T>
1273int32_t LastIndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1);
1274
1275
1281template <typename T>
1282int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value);
1283
1284
1290template <typename T>
1291int32_t LastIndexOfAnyExcept(const Span<T>& span, const T& value);
1292
1293
1299template <typename T>
1300int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values);
1301
1302
1308template <typename T>
1309int32_t LastIndexOfAnyExcept(const Span<T>& span, const ReadOnlySpan<T>& values);
1310
1311
1317template <typename T>
1318int32_t LastIndexOfAnyExcept(const Span<T>& span, const Span<T>& values);
1319
1320
1327template <typename T>
1328int32_t LastIndexOfAnyExceptInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive);
1329
1330
1337template <typename T>
1338int32_t LastIndexOfAnyExceptInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive);
1339
1340
1347template <typename T>
1348int32_t LastIndexOfAnyInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive);
1349
1350
1357template <typename T>
1358int32_t LastIndexOfAnyInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive);
1359
1360
1366template <typename T>
1367bool Overlaps(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other);
1368
1369
1375template <typename T>
1376bool Overlaps(const Span<T>& span, const ReadOnlySpan<T>& other);
1377
1378
1385template <typename T>
1386bool Overlaps(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other, int32_t& elementOffset);
1387
1388
1395template <typename T>
1396bool Overlaps(const Span<T>& span, const ReadOnlySpan<T>& other, int32_t& elementOffset);
1397
1398
1404template <typename T>
1405void Replace(Span<T>& span, const T& oldValue, const T& newValue);
1406
1407
1415template <typename T>
1416void Replace(const ReadOnlySpan<T>& source, Span<T>& destination, const T& oldValue, const T& newValue);
1417
1421template <typename T>
1422void Reverse(Span<T>& span);
1423
1429template <typename T>
1430int32_t SequenceCompareTo(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other);
1431
1437template <typename T>
1438int32_t SequenceCompareTo(const Span<T>& span, const ReadOnlySpan<T>& other);
1439
1440
1446template <typename T>
1447int32_t SequenceCompareTo(const ReadOnlySpan<T>& span, const Span<T>& other);
1448
1449
1455template <typename T>
1456bool SequenceEqual(const ReadOnlySpan<T>& first, const ReadOnlySpan<T>& second);
1457
1458
1464template <typename T>
1465bool SequenceEqual(const Span<T>& span, const ReadOnlySpan<T>& other);
1466
1467
1475template <typename T, typename TComparer>
1476bool SequenceEqual(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other, SharedPtr<TComparer>& comparer);
1477
1478
1486template <typename T, typename TComparer>
1487bool SequenceEqual(const Span<T>& span, const ReadOnlySpan<T>& other, SharedPtr<TComparer>& comparer);
1488
1489
1495template <typename T, typename TComparer>
1496void Sort(const Span<T>& span, const SharedPtr<TComparer>& comparer);
1497
1498
1502template <typename T>
1503void Sort(Span<T>& span);
1504
1505
1514template <typename TKey, typename TValue, typename TComparer>
1515void Sort(Span<TKey>& keys, Span<TValue>& values, const SharedPtr<TComparer>& comparer);
1516
1517
1525template <typename TKey, typename TValue>
1526void Sort(Span<TKey>& keys, Span<TValue>& values, System::Comparison<TKey> comparer);
1527
1528
1535template <typename TKey, typename TValue>
1536void Sort(Span<TKey>& keys, Span<TValue>& values);
1537
1538
1544template <typename T>
1545bool StartsWith(const ReadOnlySpan<T>& span, const T& value);
1546
1547
1553template <typename T>
1554bool StartsWith(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value);
1555
1556
1562template <typename T>
1563bool StartsWith(const Span<T>& span, const ReadOnlySpan<T>& value);
1564
1565
1571template <typename T>
1572bool StartsWith(const ReadOnlySpan<T>& span, const Span<T>& value);
1573
1574
1580template <typename T>
1581ReadOnlySpan<T> Trim(const ReadOnlySpan<T>& span, T trimElement);
1582
1583
1589template <typename T>
1590Span<T> Trim(Span<T>& span, T trimElement);
1591
1592
1598template <typename T>
1599ReadOnlySpan<T> Trim(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& trimElements);
1600
1601
1607template <typename T>
1608Span<T> Trim(Span<T>& span, const ReadOnlySpan<T>& trimElements);
1609
1610
1616template <typename T>
1617ReadOnlySpan<T> TrimEnd(const ReadOnlySpan<T>& span, const T& trimElement);
1618
1619
1625template <typename T>
1626Span<T> TrimEnd(Span<T>& span, const T& trimElement);
1627
1628
1634template <typename T>
1635ReadOnlySpan<T> TrimEnd(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& trimElements);
1636
1637
1643template <typename T>
1644Span<T> TrimEnd(Span<T>& span, const ReadOnlySpan<T>& trimElements);
1645
1646
1652template <typename T>
1653ReadOnlySpan<T> TrimStart(const ReadOnlySpan<T>& span, const T& trimElement);
1654
1655
1661template <typename T>
1662Span<T> TrimStart(Span<T>& span, const T& trimElement);
1663
1664
1670template <typename T>
1671ReadOnlySpan<T> TrimStart(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& trimElements);
1672
1673
1679template <typename T>
1680Span<T> TrimStart(Span<T>& span, const ReadOnlySpan<T>& trimElements);
1681
1682
1688template <typename T>
1689Span<T> TrimStart(Span<T>& span, const ReadOnlySpan<T>& trimElements);
1690
1691
1697template <typename T>
1698Span<T> TrimStart(Span<T>& span, const ReadOnlySpan<T>& trimElements);
1699
1700
1706template <typename T>
1707Span<T> TrimStart(Span<T>& span, const ReadOnlySpan<T>& trimElements);
1708
1709
1715template <typename T>
1716Span<T> TrimStart(Span<T>& span, const ReadOnlySpan<T>& trimElements);
1717
1718
1724template <typename T>
1725Span<T> TrimStart(Span<T>& span, const ReadOnlySpan<T>& trimElements);
1726
1732ASPOSECPP_SHARED_API ReadOnlySpan<char16_t> AsSpan(const String& text, int32_t start = 0, int32_t length = -1);
1733
1739ASPOSECPP_SHARED_API int32_t CompareTo(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& other,
1740 StringComparison comparisonType);
1741
1747ASPOSECPP_SHARED_API bool Contains(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& value,
1748 StringComparison comparisonType);
1749
1755ASPOSECPP_SHARED_API bool EndsWith(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& value,
1756 StringComparison comparisonType);
1757
1763ASPOSECPP_SHARED_API bool Equals(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& other,
1764 StringComparison comparisonType);
1765
1771ASPOSECPP_SHARED_API int32_t IndexOf(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& value,
1772 StringComparison comparisonType);
1773
1777ASPOSECPP_SHARED_API bool IsWhiteSpace(const ReadOnlySpan<char16_t>& span);
1778
1784ASPOSECPP_SHARED_API int32_t LastIndexOf(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& value,
1785 StringComparison comparisonType);
1786
1792ASPOSECPP_SHARED_API bool StartsWith(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& value,
1793 StringComparison comparisonType);
1794
1800ASPOSECPP_SHARED_API int32_t ToLower(const ReadOnlySpan<char16_t>& source, Span<char16_t>& destination,
1802
1807ASPOSECPP_SHARED_API int32_t ToLowerInvariant(const ReadOnlySpan<char16_t>& source, Span<char16_t>& destination);
1808
1814ASPOSECPP_SHARED_API int32_t ToUpper(const ReadOnlySpan<char16_t>& source, Span<char16_t>& destination,
1816
1821ASPOSECPP_SHARED_API int32_t ToUpperInvariant(const ReadOnlySpan<char16_t>& source, Span<char16_t>& destination);
1822
1827inline bool StartsWith(const ReadOnlySpan<String>& span, const char16_t* val)
1828{
1829 if (span.get_Length() == 0)
1830 {
1831 return false;
1832 }
1833 String value = String(val);
1834 return (span.get(0)).Equals(value);
1835}
1836
1841{
1843}
1844
1849{
1851}
1852
1857{
1859}
1860
1865{
1866 return TrimEnd<char16_t>(span, Details::DefaultWhitespaceSpan);
1867}
1868
1873inline ReadOnlySpan<char16_t> TrimEnd(const ReadOnlySpan<char16_t>& span, char16_t trimchar)
1874{
1875 int32_t endIndex = span.get_Length() - 1;
1876 while (endIndex >= 0 && span.get(endIndex) == trimchar)
1877 {
1878 --endIndex;
1879 }
1880 return span.Slice(0, endIndex + 1);
1881}
1882
1887inline Span<char16_t> TrimEnd(Span<char16_t>& span, char16_t trimchar)
1888{
1889 int32_t endIndex = span.get_Length() - 1;
1890 while (endIndex >= 0 && span.get(endIndex) == trimchar)
1891 {
1892 --endIndex;
1893 }
1894 return span.Slice(0, endIndex + 1);
1895}
1896
1902{
1903 int32_t endIndex = span.get_Length() - 1;
1904 while (endIndex >= 0 && Contains(trimChars, span.get(endIndex)))
1905 {
1906 --endIndex;
1907 }
1908 return span.Slice(0, endIndex + 1);
1909}
1910
1916{
1917 int32_t endIndex = span.get_Length() - 1;
1918 while (endIndex >= 0 && Contains(trimchars, span.get(endIndex)))
1919 {
1920 --endIndex;
1921 }
1922 return span.Slice(0, endIndex + 1);
1923}
1924
1929{
1931}
1932
1937{
1939}
1940
1945inline ReadOnlySpan<char16_t> TrimStart(const ReadOnlySpan<char16_t>& span, char16_t trimchar)
1946{
1947 int32_t startIndex = 0;
1948 while (startIndex < span.get_Length() && span.get(startIndex) == trimchar)
1949 {
1950 ++startIndex;
1951 }
1952 return span.Slice(startIndex);
1953}
1954
1959inline Span<char16_t> TrimStart(Span<char16_t>& span, char16_t trimchar)
1960{
1961 int32_t startIndex = 0;
1962 while (startIndex < span.get_Length() && span.get(startIndex) == trimchar)
1963 {
1964 ++startIndex;
1965 }
1966 return span.Slice(startIndex);
1967}
1968
1974{
1975 int32_t startIndex = 0;
1976 while (startIndex < span.get_Length() && Contains(trimchars, span.get(startIndex)))
1977 {
1978 ++startIndex;
1979 }
1980 return span.Slice(startIndex);
1981}
1982
1988{
1989 int32_t startIndex = 0;
1990 while (startIndex < span.get_Length() && Contains(trimchars, span.get(startIndex)))
1991 {
1992 ++startIndex;
1993 }
1994 return span.Slice(startIndex);
1995}
1996
1997template <typename T>
1999{
2000 return AsMemory<T>(array, 0, -1);
2001}
2002
2003template <typename T>
2004Memory<T> AsMemory(const ArrayPtr<T>& array, int32_t start)
2005{
2006 return AsMemory<T>(array, start, -1);
2007}
2008
2009template <typename T>
2010Memory<T> AsMemory(const ArrayPtr<T>& array, int32_t start, int32_t length)
2011{
2012 if (array == nullptr)
2013 {
2014 throw ArgumentNullException(u"array is null");
2015 }
2016 if (start < 0 || (length < 0 && length != -1) ||
2017 (length == -1 ? start > array->get_Length() : start + length > array->get_Length()))
2018 {
2019 throw ArgumentOutOfRangeException(u"start or length is out of range");
2020 }
2021 if (length == -1)
2022 {
2023 length = array->get_Length() - start;
2024 }
2025 return Memory<T>(array, start, length);
2026}
2027
2028template <typename T>
2030{
2031 return Memory<T>(segment.get_Array(), segment.get_Offset(), segment.get_Count());
2032}
2033
2034template <typename T>
2035Memory<T> AsMemory(const ArrayPtr<T>& array, const Range& range)
2036{
2037 if (array == nullptr)
2038 {
2039 if (!range.get_Start().Equals(Index::get_Start()) || !range.get_End().Equals(Index::get_Start()))
2040 {
2041 throw ArgumentNullException(u"array");
2042 }
2043
2044 return Memory<T>();
2045 }
2046
2047 auto ol = range.GetOffsetAndLength(array->get_Length());
2048 return Memory<T>(array, ol.template Item<0>(), ol.template Item<1>());
2049}
2050
2051template <typename T>
2052Span<T> AsSpan(const ArrayPtr<T>& array, int32_t start, int32_t length)
2053{
2054 if (array == nullptr)
2055 {
2056 throw ArgumentNullException(u"array is null");
2057 }
2058 if (start < 0 || (length < 0 && length != -1) ||
2059 (length == -1 ? start > array->get_Length() : start + length > array->get_Length()))
2060 {
2061 throw ArgumentOutOfRangeException(u"start or length is out of range");
2062 }
2063 if (length == -1)
2064 {
2065 length = array->get_Length() - start;
2066 }
2067 return Span<T>(array, start, length);
2068}
2069
2070template <typename T, typename TComparable>
2071int32_t BinarySearch(const ReadOnlySpan<T>& span, const TComparable& comparable)
2072{
2073 return Details::BinarySearchImpl(span, comparable,
2074 [](const TComparable& search_value, const T& container_value) -> int32_t {
2075 return Details::Compare(search_value, container_value);
2076 });
2077}
2078
2079template <typename T, typename TComparer>
2080int32_t BinarySearch(const ReadOnlySpan<T>& span, const T& value, const SharedPtr<TComparer>& comparerPtr)
2081{
2082 return Details::BinarySearchImpl(span, value,
2083 [&comparerPtr](const T& search_value, const T& container_value) -> int32_t {
2084 return comparerPtr->Compare(search_value, container_value);
2085 });
2086}
2087
2088template <typename T, typename TComparable>
2089int32_t BinarySearch(const Span<T>& span, const TComparable& comparable)
2090{
2091 return BinarySearch(static_cast<ReadOnlySpan<T>>(span), comparable);
2092}
2093
2094template <typename T, typename TComparer>
2095int32_t BinarySearch(const Span<T>& span, const T& value, const SharedPtr<TComparer>& comparer)
2096{
2097 return BinarySearch(static_cast<ReadOnlySpan<T>>(span), value, comparer);
2098}
2099
2100template <typename T>
2101int32_t CommonPrefixLength(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other)
2102{
2103 int32_t commonLength = 0;
2104 int32_t minLength = std::min(span.get_Length(), other.get_Length());
2105
2106 // Compare elements until a mismatch is found
2107 for (int32_t i = 0; i < minLength; ++i)
2108 {
2109 if (System::ObjectExt::Equals(span.get(i), other.get(i)))
2110 {
2111 ++commonLength;
2112 }
2113 else
2114 {
2115 break; // Mismatch found, exit early
2116 }
2117 }
2118
2119 return commonLength;
2120}
2121
2122template <typename T>
2123int32_t CommonPrefixLength(const Span<T>& span, const ReadOnlySpan<T>& other)
2124{
2125 return CommonPrefixLength(static_cast<ReadOnlySpan<T>>(span), other);
2126}
2127
2128template <typename T>
2129int32_t CommonPrefixLength(const Span<T>& span, const Span<T>& other)
2130{
2131 return CommonPrefixLength(static_cast<ReadOnlySpan<T>>(span), static_cast<ReadOnlySpan<T>>(other));
2132}
2133
2134template <typename T, typename TEqualityComparer>
2135int32_t CommonPrefixLength(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other,
2136 const SharedPtr<TEqualityComparer>& comparer)
2137{
2138 int32_t commonLength = 0;
2139 int32_t minLength = std::min(span.get_Length(), other.get_Length());
2140
2141 // Compare elements until a mismatch is found
2142 for (int32_t i = 0; i < minLength; ++i)
2143 {
2144 if ((comparer == nullptr && System::ObjectExt::Equals(span.get(i), other.get(i))) ||
2145 (comparer != nullptr && comparer->Equals(span.get(i), other.get(i))))
2146 {
2147 ++commonLength;
2148 }
2149 else
2150 {
2151 break; // Mismatch found, exit early
2152 }
2153 }
2154
2155 return commonLength;
2156}
2157
2158template <typename T, typename TEqualityComparer>
2159int32_t CommonPrefixLength(const Span<T>& span, const ReadOnlySpan<T>& other,
2160 const SharedPtr<TEqualityComparer>& comparer)
2161{
2162 return CommonPrefixLength(static_cast<ReadOnlySpan<T>>(span), other, comparer);
2163}
2164
2165template <typename T, typename TEqualityComparer>
2166int32_t CommonPrefixLength(const Span<T>& span, const Span<T>& other, const SharedPtr<TEqualityComparer>& comparer)
2167{
2168 return CommonPrefixLength(static_cast<ReadOnlySpan<T>>(span), static_cast<ReadOnlySpan<T>>(other), comparer);
2169}
2170
2171template <typename T>
2172bool Contains(const ReadOnlySpan<T>& span, const T& value)
2173{
2174 return std::find_if(span.begin(), span.end(), [&value](const T& item) { return System::ObjectExt::Equals(value, item); }) !=
2175 span.end();
2176}
2177
2178template <typename T>
2179bool Contains(const Span<T>& span, const T& value)
2180{
2181 return std::find(span.begin(), span.end(), value) != span.end();
2182}
2183
2184template <typename T>
2185bool ContainsAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
2186{
2187 return Contains(span, value0) || Contains(span, value1);
2188}
2189
2190template <typename T>
2191bool ContainsAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
2192{
2193 return Contains(span, value0) || Contains(span, value1) || Contains(span, value2);
2194}
2195
2196template <typename T>
2197bool ContainsAny(const Span<T>& span, const T& value0, const T& value1)
2198{
2199 return ContainsAny(static_cast<const ReadOnlySpan<T>&>(span), value0, value1);
2200}
2201
2202template <typename T>
2203bool ContainsAny(const Span<T>& span, const T& value0, const T& value1, const T& value2)
2204{
2205 return ContainsAny(static_cast<const ReadOnlySpan<T>&>(span), value0, value1, value2);
2206}
2207
2208template <typename T>
2209bool ContainsAny(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
2210{
2211 for (const auto& value : values)
2212 {
2213 if (Contains(span, value))
2214 {
2215 return true; // Found at least one value
2216 }
2217 }
2218 return false; // Not found
2219}
2220
2221template <typename T>
2222bool ContainsAny(const Span<T>& span, const ReadOnlySpan<T>& values)
2223{
2224 return ContainsAny(static_cast<const ReadOnlySpan<T>&>(span), values);
2225}
2226
2227template <typename T>
2228bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
2229{
2230 for (auto& member : span)
2231 {
2232 if (!System::ObjectExt::Equals(member, value0) && !System::ObjectExt::Equals(member, value1) &&
2233 !System::ObjectExt::Equals(member, value2))
2234 {
2235 return true;
2236 }
2237 }
2238 return false;
2239}
2240
2241template <typename T>
2242bool ContainsAnyExcept(const Span<T>& span, const T& value0, const T& value1, const T& value2)
2243{
2244 return ContainsAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value0, value1, value2);
2245}
2246
2247template <typename T>
2248bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
2249{
2250 for (auto& member : span)
2251 {
2252 if (!System::ObjectExt::Equals(member, value0) && !System::ObjectExt::Equals(member, value1))
2253 {
2254 return true;
2255 }
2256 }
2257 return false;
2258}
2259
2260template <typename T>
2261bool ContainsAnyExcept(const Span<T>& span, const T& value0, const T& value1)
2262{
2263 return ContainsAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value0, value1);
2264}
2265
2266template <typename T>
2267bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const T& value)
2268{
2269 for (auto& member : span)
2270 {
2271 if (!System::ObjectExt::Equals(member, value))
2272 {
2273 return true;
2274 }
2275 }
2276 return false;
2277}
2278
2279template <typename T>
2280bool ContainsAnyExcept(const Span<T>& span, const T& value)
2281{
2282 return ContainsAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value);
2283}
2284
2285template <typename T>
2286bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
2287{
2288 switch (values.get_Length())
2289 {
2290 case 0:
2291 return span.get_IsEmpty() ? false : true;
2292
2293 case 1:
2294 return ContainsAnyExcept(span, values.get(0));
2295
2296 case 2:
2297 return ContainsAnyExcept(span, values.get(0), values.get(1));
2298
2299 case 3:
2300 return ContainsAnyExcept(span, values.get(0), values.get(1), values.get(2));
2301
2302 default:
2303 for (auto& member : span)
2304 {
2305 if (!Contains(values, member))
2306 {
2307 return true;
2308 }
2309 }
2310 return false;
2311 }
2312}
2313
2314template <typename T>
2315bool ContainsAnyExcept(const Span<T>& span, const ReadOnlySpan<T>& values)
2316{
2317 return ContainsAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), values);
2318}
2319
2320template <typename T>
2321bool ContainsAnyExceptInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
2322{
2323 for (const auto& value : span)
2324 {
2325 if (value < lowInclusive || value > highInclusive)
2326 {
2327 return true; // Found a value outside the range
2328 }
2329 }
2330 return false; // All values are within the range
2331}
2332
2333template <typename T>
2334bool ContainsAnyExceptInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
2335{
2336 for (const auto& value : span)
2337 {
2338 if (value < lowInclusive || value > highInclusive)
2339 {
2340 return true; // Found a value outside the range
2341 }
2342 }
2343 return false; // All values are within the range
2344}
2345
2346template <typename T>
2347bool ContainsAnyInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
2348{
2349 for (const auto& value : span)
2350 {
2351 if (value >= lowInclusive && value <= highInclusive)
2352 {
2353 return true; // Found a value within the range
2354 }
2355 }
2356 return false; // No values found within the range
2357}
2358
2359template <typename T>
2360bool ContainsAnyInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
2361{
2362 for (const auto& value : span)
2363 {
2364 if (value >= lowInclusive && value <= highInclusive)
2365 {
2366 return true; // Found a value within the range
2367 }
2368 }
2369 return false; // No values found within the range
2370}
2371
2372template <typename T>
2373void CopyTo(const ArrayPtr<T>& source, Span<T>& destination)
2374{
2375 return ReadOnlySpan<T>(source).CopyTo(destination);
2376}
2377
2378template <typename T>
2379int32_t Count(const ReadOnlySpan<T>& span, const T& value)
2380{
2381 int32_t count = 0;
2382 for (const auto& item : span)
2383 {
2384 if (System::ObjectExt::Equals(item, value))
2385 {
2386 ++count;
2387 }
2388 }
2389 return count;
2390}
2391
2392template <typename T>
2393int32_t Count(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value)
2394{
2395 switch (value.get_Length())
2396 {
2397 case 0:
2398 return 0;
2399
2400 case 1:
2401 return Count(span, value.get(0));
2402
2403 default:
2404 int32_t count = 0;
2405 int32_t pos = 0;
2406 ReadOnlySpan<T> currentSpan = span;
2407 while ((pos = IndexOf(currentSpan, value)) >= 0)
2408 {
2409 count++;
2410 currentSpan = currentSpan.Slice(pos + value.get_Length());
2411 }
2412 return count;
2413 }
2414}
2415
2416template <typename T>
2417int32_t Count(const Span<T>& span, const T& value)
2418{
2419 return Count(ReadOnlySpan<T>(span), value); // Delegate to ReadOnlySpan<T> method
2420}
2421
2422template <typename T>
2423int32_t Count(const Span<T>& span, const ReadOnlySpan<T>& value)
2424{
2425 return Count(ReadOnlySpan<T>(span), value); // Delegate to ReadOnlySpan<T> method
2426}
2427
2428template <typename T>
2429bool EndsWith(const ReadOnlySpan<T>& span, const T& value)
2430{
2431 if (span.get_Length() == 0)
2432 {
2433 return false; // Empty span does not end with any value
2434 }
2435 return System::ObjectExt::Equals(span.get(span.get_Length() - 1), value);
2436}
2437
2438template <typename T>
2439bool EndsWith(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value)
2440{
2441 int32_t spanLength = span.get_Length();
2442 int32_t valueLength = value.get_Length();
2443
2444 if (valueLength > spanLength)
2445 {
2446 return false;
2447 }
2448
2449 if (valueLength == spanLength)
2450 {
2451 return SequenceEqual(span, value);
2452 }
2453
2454 return SequenceEqual(span.Slice(spanLength - valueLength), value);
2455}
2456
2457template <typename T>
2458bool EndsWith(const Span<T>& span, const ReadOnlySpan<T>& value)
2459{
2460 return EndsWith(ReadOnlySpan<T>(span), value);
2461}
2462
2463template <typename T>
2464bool EndsWith(const ReadOnlySpan<T>& span, const Span<T>& value)
2465{
2466 return EndsWith(span, ReadOnlySpan<T>(value));
2467}
2468
2469template <typename T>
2470bool EndsWith(const Span<T>& span, const Span<T>& value)
2471{
2472 return EndsWith(ReadOnlySpan<T>(span), ReadOnlySpan<T>(value));
2473}
2474
2475template <typename T>
2476int32_t IndexOf(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value)
2477{
2478 if (value.get_Length() == 0)
2479 {
2480 return 0; // A zero-length sequence is always treated as "found" at the start of the search space.
2481 }
2482
2483 const T& valueHead = value.get(0);
2484 int32_t valueTailLength = value.get_Length() - 1;
2485
2486 int32_t index = 0;
2487 while (true)
2488 {
2489 if (index + valueTailLength > span.get_Length())
2490 {
2491 break; // The unsearched portion is now shorter than the sequence we're looking for.
2492 }
2493
2494 // Search for the first element of "value".
2495 int32_t remainingSearchSpaceLength = span.get_Length() - index - valueTailLength;
2496 int32_t relativeIndex = -1; // Default to not found
2497
2498 for (int32_t i = 0; i < remainingSearchSpaceLength; ++i)
2499 {
2500 if (System::ObjectExt::Equals(span.get(index + i), valueHead))
2501 {
2502 relativeIndex = i;
2503 break;
2504 }
2505 }
2506
2507 if (relativeIndex == -1)
2508 {
2509 break; // First element not found.
2510 }
2511
2512 index += relativeIndex;
2513
2514 // Found the first element of "value". Check if the tail matches.
2515 bool tailMatches = true;
2516 for (int32_t i = 0; i < valueTailLength; ++i)
2517 {
2518 if (span.get(index + 1 + i) != value.get(1 + i))
2519 {
2520 tailMatches = false;
2521 break;
2522 }
2523 }
2524
2525 if (tailMatches)
2526 {
2527 return index; // The tail matched. Return a successful find.
2528 }
2529
2530 ++index; // Move to the next position in the search space.
2531 }
2532
2533 return -1; // Not found.
2534}
2535
2536template <typename T>
2537int32_t IndexOf(const ReadOnlySpan<T>& span, const T& value)
2538{
2539 for (int32_t i = 0; i < span.get_Length(); ++i)
2540 {
2541 if (System::ObjectExt::Equals(span.get(i), value))
2542 {
2543 return i; // Found
2544 }
2545 }
2546 return -1; // Not found
2547}
2548
2549template <typename T>
2550int32_t IndexOf(const Span<T>& span, const ReadOnlySpan<T>& value)
2551{
2552 return IndexOf(static_cast<ReadOnlySpan<T>>(span), value);
2553}
2554
2555template <typename T>
2556int32_t IndexOf(const Span<T>& span, const T& value)
2557{
2558 return IndexOf(static_cast<ReadOnlySpan<T>>(span), value);
2559}
2560
2561template <typename T>
2562int32_t IndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
2563{
2564 for (int32_t i = 0; i < span.get_Length(); ++i)
2565 {
2566 if (System::ObjectExt::Equals(span.get(i), value0) || System::ObjectExt::Equals(span.get(i), value1))
2567 {
2568 return i; // Found
2569 }
2570 }
2571 return -1; // Not found
2572}
2573
2574template <typename T>
2575int32_t IndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
2576{
2577 for (int32_t i = 0; i < span.get_Length(); ++i)
2578 {
2579 if (System::ObjectExt::Equals(span.get(i), value0) || System::ObjectExt::Equals(span.get(i), value1) ||
2580 System::ObjectExt::Equals(span.get(i), value2))
2581 {
2582 return i; // Found
2583 }
2584 }
2585 return -1; // Not found
2586}
2587
2588template <typename T>
2589int32_t IndexOfAny(const Span<T>& span, const T& value0, const T& value1)
2590{
2591 return IndexOfAny(static_cast<ReadOnlySpan<T>>(span), value0, value1);
2592}
2593
2594template <typename T>
2595int32_t IndexOfAny(const Span<T>& span, const T& value0, const T& value1, const T& value2)
2596{
2597 return IndexOfAny(static_cast<ReadOnlySpan<T>>(span), value0, value1, value2);
2598}
2599
2600template <typename T>
2601int32_t IndexOfAny(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
2602{
2603 for (int32_t i = 0; i < span.get_Length(); ++i)
2604 {
2605 for (int32_t j = 0; j < values.get_Length(); ++j)
2606 {
2607 if (System::ObjectExt::Equals(span.get(i), values.get(j)))
2608 {
2609 return i; // Found
2610 }
2611 }
2612 }
2613 return -1; // Not found
2614}
2615
2616template <typename T>
2617int32_t IndexOfAny(const Span<T>& span, const ReadOnlySpan<T>& values)
2618{
2619 return IndexOfAny(static_cast<ReadOnlySpan<T>>(span), values);
2620}
2621
2622template <typename T>
2623int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value)
2624{
2625 for (int32_t i = 0; i < span.get_Length(); ++i)
2626 {
2627 if (!System::ObjectExt::Equals(span.get(i), value))
2628 {
2629 return i; // Found
2630 }
2631 }
2632 return -1; // Not found
2633}
2634
2635template <typename T>
2636int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
2637{
2638 for (int32_t i = 0; i < span.get_Length(); ++i)
2639 {
2640 if (!System::ObjectExt::Equals(span.get(i), value0) && !System::ObjectExt::Equals(span.get(i), value1))
2641 {
2642 return i; // Found
2643 }
2644 }
2645 return -1; // Not found
2646}
2647
2648template <typename T>
2649int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
2650{
2651 for (int32_t i = 0; i < span.get_Length(); ++i)
2652 {
2653 if (!System::ObjectExt::Equals(span.get(i), value0) && !System::ObjectExt::Equals(span.get(i), value1) &&
2654 !System::ObjectExt::Equals(span.get(i), value2))
2655 {
2656 return i; // Found
2657 }
2658 }
2659 return -1; // Not found
2660}
2661
2662template <typename T>
2663int32_t IndexOfAnyExcept(const Span<T>& span, const T& value)
2664{
2665 return IndexOfAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value);
2666}
2667
2668template <typename T>
2669int32_t IndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1)
2670{
2671 return IndexOfAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value0, value1);
2672}
2673
2674template <typename T>
2675int32_t IndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1, const T& value2)
2676{
2677 return IndexOfAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value0, value1, value2);
2678}
2679
2680template <typename T>
2681int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
2682{
2683 for (int32_t i = 0; i < span.get_Length(); ++i)
2684 {
2685 bool found = false;
2686 for (int32_t j = 0; j < values.get_Length(); ++j)
2687 {
2688 if (System::ObjectExt::Equals(span.get(i), values.get(j)))
2689 {
2690 found = true;
2691 break;
2692 }
2693 }
2694 if (!found)
2695 {
2696 return i; // Found
2697 }
2698 }
2699 return -1; // Not found
2700}
2701
2702template <typename T>
2703int32_t IndexOfAnyExcept(const Span<T>& span, const ReadOnlySpan<T>& values)
2704{
2705 return IndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), values);
2706}
2707
2708template <typename T>
2709int32_t IndexOfAnyExceptInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
2710{
2711 for (int32_t i = 0; i < span.get_Length(); ++i)
2712 {
2713 if (Details::Compare(span.get(i), lowInclusive) < 0 || Details::Compare(span.get(i), highInclusive) > 0)
2714 {
2715 return i; // Found an element outside the range
2716 }
2717 }
2718 return -1; // Not found
2719}
2720
2721template <typename T>
2722int32_t IndexOfAnyExceptInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
2723{
2724 return IndexOfAnyExceptInRange(static_cast<const ReadOnlySpan<T>&>(span), lowInclusive, highInclusive);
2725}
2726
2727template <typename T>
2728int32_t IndexOfAnyInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
2729{
2730 for (int32_t i = 0; i < span.get_Length(); ++i)
2731 {
2732 // if (span.get(i).CompareTo(lowInclusive) >= 0 && span.get(i).CompareTo(highInclusive) <= 0) {
2733 if (Details::Compare(span.get(i), lowInclusive) >= 0 && Details::Compare(span.get(i), highInclusive) <= 0)
2734 {
2735 return i; // Found an element within the range
2736 }
2737 }
2738 return -1; // Not found
2739}
2740
2741template <typename T>
2742int32_t IndexOfAnyInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
2743{
2744 return IndexOfAnyInRange(static_cast<const ReadOnlySpan<T>&>(span), lowInclusive, highInclusive);
2745}
2746
2747template <typename T>
2748int32_t LastIndexOf(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value)
2749{
2750 if (value.get_Length() == 0)
2751 return span.get_Length(); // A zero-length sequence is always treated as "found" at the end of the search space.
2752
2753 int32_t valueTailLength = value.get_Length() - 1;
2754 if (valueTailLength == 0)
2755 {
2756 return LastIndexOf<T>(span, value.get(0));
2757 }
2758
2759 int32_t index = 0;
2760
2761 T valueHead = value.get(0);
2762 ReadOnlySpan<T> valueTail = value.Slice(1);
2763
2764 while (true)
2765 {
2766 int32_t remainingSearchSpaceLength = span.get_Length() - index - valueTail.get_Length(); // отступ
2767 if (remainingSearchSpaceLength <= 0)
2768 break;
2769
2770 // Do a quick search for the first element of "value".
2771 int32_t relativeIndex = Details::LastIndexOfImpl<T>(span, remainingSearchSpaceLength, valueHead);
2772 if (relativeIndex < 0)
2773 break;
2774
2775 // Found the first element of "value". See if the tail matches.
2776 if (Details::SequenceEqualImpl<T>(span, relativeIndex + 1, valueTail.get_Length(), valueTail))
2777 return relativeIndex;
2778
2779 index += remainingSearchSpaceLength - relativeIndex;
2780 }
2781 return -1;
2782}
2783
2784template <typename T>
2785int32_t LastIndexOf(const ReadOnlySpan<T>& span, const T& value)
2786{
2787 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
2788 {
2789 if (System::ObjectExt::Equals(span.get(i), value))
2790 {
2791 return i; // Found
2792 }
2793 }
2794 return -1; // Not found
2795}
2796
2797template <typename T>
2798int32_t LastIndexOf(const Span<T>& span, const ReadOnlySpan<T>& value)
2799{
2800 return LastIndexOf(static_cast<const ReadOnlySpan<T>&>(span), value); // Cast for use with ReadOnlySpan
2801}
2802
2803template <typename T>
2804int32_t LastIndexOf(const Span<T>& span, const T& value)
2805{
2806 return LastIndexOf(static_cast<const ReadOnlySpan<T>&>(span), value); // Cast for use with ReadOnlySpan
2807}
2808
2809template <typename T>
2810int32_t LastIndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
2811{
2812 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
2813 {
2814 if (System::ObjectExt::Equals(span.get(i), value0) || System::ObjectExt::Equals(span.get(i), value1) ||
2815 System::ObjectExt::Equals(span.get(i), value2))
2816 {
2817 return i; // Found
2818 }
2819 }
2820 return -1; // Not found
2821}
2822
2823template <typename T>
2824int32_t LastIndexOfAny(const Span<T>& span, const T& value0, const T& value1, const T& value2)
2825{
2826 return LastIndexOfAny(static_cast<const ReadOnlySpan<T>&>(span), value0, value1, value2);
2827}
2828
2829template <typename T>
2830int32_t LastIndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
2831{
2832 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
2833 {
2834 if (System::ObjectExt::Equals(span.get(i), value0) || System::ObjectExt::Equals(span.get(i), value1))
2835 {
2836 return i; // Found
2837 }
2838 }
2839 return -1; // Not found
2840}
2841
2842template <typename T>
2843int32_t LastIndexOfAny(const Span<T>& span, const T& value0, const T& value1)
2844{
2845 return LastIndexOfAny(static_cast<const ReadOnlySpan<T>&>(span), value0, value1);
2846}
2847
2848template <typename T>
2849int32_t LastIndexOfAny(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
2850{
2851 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
2852 {
2853 for (int32_t j = 0; j < values.get_Length(); ++j)
2854 {
2855 if (System::ObjectExt::Equals(span.get(i), values.get(j)))
2856 {
2857 return i; // Found
2858 }
2859 }
2860 }
2861 return -1; // Not found
2862}
2863
2864template <typename T>
2865int32_t LastIndexOfAny(const Span<T>& span, const ReadOnlySpan<T>& values)
2866{
2867 return LastIndexOfAny(static_cast<const ReadOnlySpan<T>&>(span), values);
2868}
2869
2870template <typename T>
2871int32_t LastIndexOfAny(const Span<T>& span, const Span<T>& values)
2872{
2873 return LastIndexOfAny(static_cast<const ReadOnlySpan<T>&>(span), static_cast<const ReadOnlySpan<T>&>(values));
2874}
2875
2876template <typename T>
2877int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
2878{
2879 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
2880 {
2881 const T& current = span.get(i);
2882 if (!(System::ObjectExt::Equals(current, value0) || System::ObjectExt::Equals(current, value1) ||
2883 System::ObjectExt::Equals(current, value2)))
2884 {
2885 return i;
2886 }
2887 }
2888 return -1; // Not found
2889}
2890
2891template <typename T>
2892int32_t LastIndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1, const T& value2)
2893{
2894 return LastIndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), value0, value1, value2);
2895}
2896
2897template <typename T>
2898int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
2899{
2900 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
2901 {
2902 const T& current = span.get(i);
2903 if (!(System::ObjectExt::Equals(current, value0) || System::ObjectExt::Equals(current, value1)))
2904 {
2905 return i;
2906 }
2907 }
2908 return -1; // Not found
2909}
2910
2911template <typename T>
2912int32_t LastIndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1)
2913{
2914 return LastIndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), value0, value1);
2915}
2916
2917template <typename T>
2918int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value)
2919{
2920 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
2921 {
2922 T current = span.get(i);
2923 if (!(System::ObjectExt::Equals(current, value)))
2924 {
2925 return i;
2926 }
2927 }
2928 return -1; // Not found
2929}
2930
2931template <typename T>
2932int32_t LastIndexOfAnyExcept(const Span<T>& span, const T& value)
2933{
2934 return LastIndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), value);
2935}
2936
2937template <typename T>
2938int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
2939{
2940 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
2941 {
2942 const T& current = span.get(i);
2943 bool found = false;
2944 for (auto& value : values)
2945 {
2946 if (System::ObjectExt::Equals(current, value))
2947 {
2948 found = true;
2949 break;
2950 }
2951 }
2952 if (!found)
2953 {
2954 return i;
2955 }
2956 }
2957 return -1; // Not found
2958}
2959
2960template <typename T>
2961int32_t LastIndexOfAnyExcept(const Span<T>& span, const ReadOnlySpan<T>& values)
2962{
2963 return LastIndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), values);
2964}
2965
2966template <typename T>
2967int32_t LastIndexOfAnyExcept(const Span<T>& span, const Span<T>& values)
2968{
2969 return LastIndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), static_cast<ReadOnlySpan<T>>(values));
2970}
2971
2972template <typename T>
2973int32_t LastIndexOfAnyExceptInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
2974{
2975 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
2976 {
2977 if (Details::Compare(span.get(i), lowInclusive) < 0 || Details::Compare(span.get(i), highInclusive) > 0)
2978 {
2979 return i; // Found an element outside the range
2980 }
2981 }
2982 return -1; // Not found
2983}
2984
2985template <typename T>
2986int32_t LastIndexOfAnyExceptInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
2987{
2988 return LastIndexOfAnyExceptInRange(static_cast<ReadOnlySpan<T>>(span), lowInclusive, highInclusive);
2989}
2990
2991template <typename T>
2992int32_t LastIndexOfAnyInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
2993{
2994 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
2995 {
2996 if (Details::Compare(span.get(i), lowInclusive) >= 0 && Details::Compare(span.get(i), highInclusive) <= 0)
2997 {
2998 return i; // Found an element outside the range
2999 }
3000 }
3001 return -1; // Not found
3002}
3003
3004template <typename T>
3005int32_t LastIndexOfAnyInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
3006{
3007 return LastIndexOfAnyInRange(static_cast<ReadOnlySpan<T>>(span), lowInclusive, highInclusive);
3008}
3009
3010template <typename T>
3011bool Overlaps(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other)
3012{
3013 int32_t offset;
3014 return Overlaps(span, other, offset);
3015}
3016
3017template <typename T>
3018bool Overlaps(const Span<T>& span, const ReadOnlySpan<T>& other)
3019{
3020 return Overlaps(static_cast<ReadOnlySpan<T>>(span), other);
3021}
3022
3023template <typename T>
3024bool Overlaps(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other, int32_t& elementOffset)
3025{
3026 if (span.get_IsEmpty() || other.get_IsEmpty())
3027 {
3028 elementOffset = 0;
3029 return false;
3030 }
3031 ptrdiff_t Offset = other.begin() - span.begin();
3032 bool isOverlap = (Offset >= 0 && Offset < span.get_Length()) || (Offset < 0 && -Offset < other.get_Length());
3033
3034 if (isOverlap)
3035 {
3036 elementOffset = static_cast<int32_t>(Offset);
3037 }
3038 else
3039 {
3040 elementOffset = 0;
3041 }
3042 return isOverlap;
3043}
3044
3045template <typename T>
3046bool Overlaps(const Span<T>& span, const ReadOnlySpan<T>& other, int32_t& elementOffset)
3047{
3048 return Overlaps(static_cast<ReadOnlySpan<T>>(span), other, elementOffset);
3049}
3050
3051template <typename T>
3052void Replace(Span<T>& span, const T& oldValue, const T& newValue)
3053{
3054 for (int32_t i = 0; i < span.get_Length(); ++i)
3055 {
3056 if (System::ObjectExt::Equals(span.get(i), oldValue))
3057 {
3058 span.get(i) = newValue; // Replace oldValue with newValue
3059 }
3060 }
3061}
3062
3063template <typename T>
3064void Replace(const ReadOnlySpan<T>& source, Span<T>& destination, const T& oldValue, const T& newValue)
3065{
3066 if (destination.get_Length() < source.get_Length())
3067 {
3068 throw ArgumentException(u"Destination span is smaller than source span.");
3069 }
3070
3071 for (int32_t i = 0; i < source.get_Length(); ++i)
3072 {
3073 if (System::ObjectExt::Equals(source.get(i), oldValue))
3074 {
3075 destination.get(i) = newValue; // Replace oldValue with newValue
3076 }
3077 else
3078 {
3079 destination.get(i) = source.get(i); // Copy the original value
3080 }
3081 }
3082}
3083
3084template <typename T>
3085void Reverse(Span<T>& span)
3086{
3087 int32_t left = 0;
3088 int32_t right = span.get_Length() - 1;
3089 while (left < right)
3090 {
3091 std::swap(span.get(left), span.get(right));
3092 ++left;
3093 --right;
3094 }
3095}
3096
3097template <typename T>
3098int32_t SequenceCompareTo(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other)//span.begin() ++
3099{
3100 auto spanIt = span.begin();
3101 auto otherIt = other.begin();
3102 auto spanEnd = span.end();
3103 auto otherEnd = other.end();
3104
3105 while (spanIt != spanEnd && otherIt != otherEnd)
3106 {
3107 if (*spanIt < *otherIt)
3108 {
3109 return -1; // span is less than other
3110 }
3111 if (*spanIt > *otherIt)
3112 {
3113 return 1; // span is greater than other
3114 }
3115
3116 ++spanIt;
3117 ++otherIt;
3118 }
3119
3120 // If all elements are equal up to the length of the shorter span
3121 if (span.get_Length() < other.get_Length())
3122 {
3123 return -1; // span is shorter
3124 }
3125 if (span.get_Length() > other.get_Length())
3126 {
3127 return 1; // span is longer
3128 }
3129
3130 return 0; // spans are equal
3131}
3132
3133template <typename T>
3134int32_t SequenceCompareTo(const Span<T>& span, const ReadOnlySpan<T>& other)
3135{
3136 return SequenceCompareTo(static_cast<ReadOnlySpan<T>>(span), other);
3137}
3138
3139template <typename T>
3140int32_t SequenceCompareTo(const ReadOnlySpan<T>& span, const Span<T>& other)
3141{
3142 return SequenceCompareTo(span, static_cast<ReadOnlySpan<T>>(other));
3143}
3144
3145template <typename T>
3146bool SequenceEqual(const ReadOnlySpan<T>& first, const ReadOnlySpan<T>& second)
3147{
3148 if (first == second)
3149 return true;
3150
3151 if (first.get_Length() != second.get_Length())
3152 {
3153 return false;
3154 }
3155
3156 int32_t length = second.get_Length();
3157
3158 return Details::SequenceEqualImpl(first, 0, first.get_Length(), second);
3159}
3160
3161template <typename T>
3162bool SequenceEqual(const Span<T>& span, const ReadOnlySpan<T>& other)
3163{
3164 return SequenceEqual(static_cast<ReadOnlySpan<T>>(span), other);
3165}
3166
3167template <typename T, typename TComparer>
3168bool SequenceEqual(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other, SharedPtr<TComparer>& comparer)
3169{
3170 if (comparer == nullptr)
3171 {
3172 return SequenceEqual(span, other);
3173 }
3174
3175 if (span.get_Length() != other.get_Length())
3176 {
3177 return false; // Lengths are not equal
3178 }
3179
3180 for (int32_t i = 0; i < span.get_Length(); ++i)
3181 {
3182 if (!comparer->Equals(span.get(i), other.get(i)))
3183 {
3184 return false; // Elements are not equal
3185 }
3186 }
3187 return true; // All elements are equal
3188}
3189
3190template <typename T, typename TComparer>
3191bool SequenceEqual(const Span<T>& span, const ReadOnlySpan<T>& other, SharedPtr<TComparer>& comparer)
3192{
3193 return SequenceEqual(static_cast<ReadOnlySpan<T>>(span), other, comparer);
3194}
3195
3196template <typename T, typename TComparer>
3197void Sort(const Span<T>& span, const SharedPtr<TComparer>& comparer)
3198{
3199 std::sort(span.begin(), span.end(), [&comparer](const T& a, const T& b) -> bool { return comparer->Compare(a, b) < 0; });
3200}
3201
3202template <typename T>
3203void Sort(Span<T>& span)
3204{
3205 std::sort(span.begin(), span.end());
3206}
3207
3208template <typename TKey, typename TValue, typename TComparer>
3209void Sort(Span<TKey>& keys, Span<TValue>& values, const SharedPtr<TComparer>& comparer)
3210{
3211 if (keys.get_Length() != values.get_Length())
3212 {
3213 throw ArgumentException(u"Keys and items must have the same length.");
3214 }
3215 if (keys.get_Length() > 1)
3216 {
3217 int32_t depthLimit = 2 * (static_cast<int32_t>(std::log2(keys.get_Length())) + 1);
3218 Details::IntroSort<TKey, TValue>(keys, values, depthLimit,
3219 [&comparer](TKey a, TKey b) -> bool { return comparer->Compare(a, b) > 0; });
3220 }
3221}
3222
3223template <typename TKey, typename TValue>
3225{
3226 if (keys.get_Length() != values.get_Length())
3227 {
3228 throw ArgumentException(u"Keys and items must have the same length.");
3229 }
3230 if (keys.get_Length() > 1)
3231 {
3232 int32_t depthLimit = 2 * (static_cast<int32_t>(std::log2(keys.get_Length())) + 1);
3233 Details::IntroSort<TKey, TValue>(keys, values, depthLimit,
3234 [&](const TKey& a, const TKey& b) { return !comparer(a, b); });
3235 }
3236}
3237
3238template <typename TKey, typename TValue>
3239void Sort(Span<TKey>& keys, Span<TValue>& values)
3240{
3241 if (keys.get_Length() != values.get_Length())
3242 {
3243 throw ArgumentException(u"Keys and items must have the same length.");
3244 }
3245 if (keys.get_Length() > 1)
3246 {
3247 int32_t depthLimit = 2 * (static_cast<int32_t>(std::log2(keys.get_Length())) + 1);
3248 Details::IntroSort<TKey, TValue>(keys, values, depthLimit, [&](const TKey& a, const TKey& b) { return a > b; });
3249 }
3250}
3251
3252template <typename T>
3253bool StartsWith(const ReadOnlySpan<T>& span, const T& value)
3254{
3255 if (span.get_Length() == 0)
3256 {
3257 return false; // Empty span cannot start with a value
3258 }
3259 return System::ObjectExt::Equals<T>(span.get(0), value);
3260}
3261
3262template <typename T>
3263bool StartsWith(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value)
3264{
3265 if (value.get_Length() > span.get_Length())
3266 {
3267 return false;
3268 }
3269
3270 for (int32_t i = 0; i < value.get_Length(); ++i)
3271 {
3272 if (!System::ObjectExt::Equals(span.get(i), value.get(i)))
3273 {
3274 return false;
3275 }
3276 }
3277
3278 return true;
3279}
3280
3281template <typename T>
3282bool StartsWith(const Span<T>& span, const ReadOnlySpan<T>& value)
3283{
3284 return StartsWith(static_cast<ReadOnlySpan<T>>(span), value);
3285}
3286
3287template <typename T>
3288bool StartsWith(const ReadOnlySpan<T>& span, const Span<T>& value)
3289{
3290 return StartsWith(span, static_cast<ReadOnlySpan<T>>(value));
3291}
3292
3293template <typename T>
3294ReadOnlySpan<T> Trim(const ReadOnlySpan<T>& span, T trimElement)
3295{
3296 return Trim(span, ReadOnlySpan<T>(&trimElement, 1));
3297}
3298
3299template <typename T>
3300Span<T> Trim(Span<T>& span, T trimElement)
3301{
3302 return Trim(span, ReadOnlySpan<T>(&trimElement, 1));
3303}
3304
3305template <typename T>
3306ReadOnlySpan<T> Trim(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& trimElements)
3307{
3308 if (span.get_IsEmpty())
3309 {
3310 return span;
3311 }
3312
3313 int32_t start = 0;
3314 int32_t end = span.get_Length() - 1;
3315
3316 // Trim from the start
3317 while (start <= end && Contains(trimElements, span.get(start)))
3318 {
3319 start++;
3320 }
3321
3322 // Trim from the end
3323 while (end >= start && Contains(trimElements, span.get(end)))
3324 {
3325 end--;
3326 }
3327
3328 return span.Slice(start, end - start + 1);
3329}
3330
3331template <typename T>
3332Span<T> Trim(Span<T>& span, const ReadOnlySpan<T>& trimElements)
3333{
3334 if (span.get_IsEmpty())
3335 {
3336 return span;
3337 }
3338
3339 int32_t start = 0;
3340 int32_t end = span.get_Length() - 1;
3341
3342 // Trim from the start
3343 while (start <= end && Contains(trimElements, span.get(start)))
3344 {
3345 start++;
3346 }
3347
3348 // Trim from the end
3349 while (end >= start && Contains(trimElements, span.get(end)))
3350 {
3351 end--;
3352 }
3353
3354 return span.Slice(start, end - start + 1);
3355}
3356
3357template <typename T>
3358ReadOnlySpan<T> TrimEnd(const ReadOnlySpan<T>& span, const T& trimElement)
3359{
3360 int32_t endIndex = span.get_Length() - 1;
3361 while (endIndex >= 0 && System::ObjectExt::Equals(span.get(endIndex), trimElement))
3362 {
3363 --endIndex;
3364 }
3365 return span.Slice(0, endIndex + 1);
3366}
3367
3368template <typename T>
3369Span<T> TrimEnd(Span<T>& span, const T& trimElement)
3370{
3371 int32_t endIndex = span.get_Length() - 1;
3372 while (endIndex >= 0 && System::ObjectExt::Equals(span.get(endIndex), trimElement)) // equals
3373 {
3374 --endIndex;
3375 }
3376 return span.Slice(0, endIndex + 1);
3377}
3378
3379template <typename T>
3381{
3382 int32_t endIndex = span.get_Length() - 1;
3383 while (endIndex >= 0 && Contains(trimElements, span.get(endIndex)))
3384 {
3385 --endIndex;
3386 }
3387 return span.Slice(0, endIndex + 1);
3388}
3389
3390template <typename T>
3391Span<T> TrimEnd(Span<T>& span, const ReadOnlySpan<T>& trimElements)
3392{
3393 int32_t endIndex = span.get_Length() - 1;
3394 while (endIndex >= 0 && Contains(trimElements, span.get(endIndex)))
3395 {
3396 --endIndex;
3397 }
3398 return span.Slice(0, endIndex + 1);
3399}
3400
3401template <typename T>
3402ReadOnlySpan<T> TrimStart(const ReadOnlySpan<T>& span, const T& trimElement)
3403{
3404 int32_t startIndex = 0;
3405 while (startIndex < span.get_Length() && System::ObjectExt::Equals(span.get(startIndex), trimElement))
3406 {
3407 ++startIndex;
3408 }
3409 return span.Slice(startIndex);
3410}
3411
3412template <typename T>
3413Span<T> TrimStart(Span<T>& span, const T& trimElement)
3414{
3415 int32_t startIndex = 0;
3416 while (startIndex < span.get_Length() && System::ObjectExt::Equals(span.get(startIndex), trimElement))
3417 {
3418 ++startIndex;
3419 }
3420 return span.Slice(startIndex);
3421}
3422
3423template <typename T>
3425{
3426 int32_t startIndex = 0;
3427 while (startIndex < span.get_Length() && Contains(trimElements, span.get(startIndex)))
3428 {
3429 ++startIndex;
3430 }
3431 return span.Slice(startIndex);
3432}
3433
3434template <typename T>
3435Span<T> TrimStart(Span<T>& span, const ReadOnlySpan<T>& trimElements)
3436{
3437 int32_t startIndex = 0;
3438 while (startIndex < span.get_Length() && Contains(trimElements, span.get(startIndex)))
3439 {
3440 ++startIndex;
3441 }
3442 return span.Slice(startIndex);
3443}
3444} // namespace MemoryExtensions
3445} // namespace System
3446#endif // _aspose_system_memory_extensions_
3447
Represents a segment of the one-dimensional array. This type should be allocated on stack and passed ...
Definition: array_segment.h:62
int32_t get_Count() const
Definition: array_segment.h:80
System::ArrayPtr< T > get_Array() const
Definition: array_segment.h:70
int32_t get_Offset() const
Definition: array_segment.h:75
Represents a pointer to the method that compares two objects of the same type. This type should be al...
Definition: comparison.h:93
bool Equals(const Index &other) const
Determines whether the current instance and the specified Index represent the same position.
Definition: index.h:75
static constexpr Index get_Start() noexcept
Gets an Index object representing the start of a collection.
Definition: index.h:41
Represents a mutable memory segment backed by an array.
Definition: memory.h:154
static std::enable_if< IsExceptionWrapper< T >::value, bool >::type Equals(const T &obj, const T2 &another)
Definition: object_ext.h:36
Represents a range with a start and end index. This type should be allocated on stack and passed to f...
Definition: range.h:14
const Index & get_End() const noexcept
Gets the End index.
Definition: range.h:56
System::ValueTuple< int32_t, int32_t > GetOffsetAndLength(int32_t length) const
Computes the zero-based start offset and length for the specified collection length.
Definition: range.h:65
const Index & get_Start() const noexcept
Gets the Start index.
Definition: range.h:50
Represents a read-only memory segment backed by an array.
Definition: memory.h:232
Forward to use within Span class.
Definition: span.h:404
Pointer class to wrap types being allocated on heap. Use it to manage memory for classes inheriting O...
Definition: smart_ptr.h:180
Represents a contiguous region of arbitrary memory similar to C++20's std::span.
Definition: span.h:364
String class used across the library. Is a substitute for C# System.String when translating code....
Definition: string.h:125
bool SequenceEqualImpl(const ReadOnlySpan< T > &first, const int32_t start, int32_t length, const ReadOnlySpan< T > &second)
Checks if two spans are equal starting from specified positions.
Definition: memory_extensions.h:226
void SwapIfGreaterWithValues(Span< TKey > &keys, Span< TValue > &values, std::function< int32_t(const TKey &, const TKey &)> comparer, int32_t i, int32_t j)
Swaps key-value pairs if comparison condition is met.
Definition: memory_extensions.h:311
int32_t PickPivotAndPartition(Span< TKey > &keys, Span< TValue > &values, std::function< int32_t(const TKey &, const TKey &)> comparer)
Selects pivot and partitions key-value pairs for quicksort.
Definition: memory_extensions.h:388
void HeapSort(Span< TKey > &keys, Span< TValue > &values, std::function< int32_t(const TKey &, const TKey &)> comparer)
Performs heap sort on key-value pairs.
Definition: memory_extensions.h:343
const std::array< char16_t, 22 > DefaultWhitespaceChars
Default whitespace characters used for trimming operations.
void InsertionSort(Span< TKey > &keys, Span< TValue > &values, std::function< int32_t(const TKey &, const TKey &)> comparer)
Performs insertion sort on key-value pairs.
Definition: memory_extensions.h:322
const ReadOnlySpan< char16_t > DefaultWhitespaceSpan
Static ReadOnlySpan for default whitespace characters to avoid array creation.
int32_t LastIndexOfImpl(const ReadOnlySpan< T > &searchSpace, int32_t length, const T &value)
Finds the last index of a value in a span.
Definition: memory_extensions.h:186
int32_t Compare(const SharedPtr< T > &a, const SharedPtr< U > &b)
Compares two smart pointers.
Definition: memory_extensions.h:153
int32_t BinarySearchImpl(const ReadOnlySpan< T > &span, const TValue &value, TCompareFunc compareFunc)
Common binary search implementation.
Definition: memory_extensions.h:435
void Heapify(Span< TKey > &keys, Span< TValue > &values, int32_t n, int32_t i, std::function< int32_t(const TKey &, const TKey &)> comparer)
Maintains heap property for key-value pairs.
Definition: memory_extensions.h:362
void IntroSort(Span< TKey > &keys, Span< TValue > &values, int32_t depthLimit, std::function< int32_t(const TKey &, const TKey &)> comparer)
Internal implementation of introsort algorithm for key-value pairs.
Definition: memory_extensions.h:263
int32_t BinarySearch(const ReadOnlySpan< T > &span, const TComparable &comparable)
Performs binary search on a sorted span.
Definition: memory_extensions.h:2071
int32_t SequenceCompareTo(const ReadOnlySpan< T > &span, const ReadOnlySpan< T > &other)
Compares two ReadOnlySpans lexicographically.
Definition: memory_extensions.h:3098
int32_t IndexOfAny(const ReadOnlySpan< T > &span, const T &value0, const T &value1)
Finds the index of the first occurrence of any of two specified values in a ReadOnlySpan<T>
Definition: memory_extensions.h:2562
bool Overlaps(const ReadOnlySpan< T > &span, const ReadOnlySpan< T > &other)
Determines if two ReadOnlySpans overlap in memory without calculating offset.
Definition: memory_extensions.h:3011
int32_t LastIndexOfAnyExceptInRange(const ReadOnlySpan< T > &span, const T &lowInclusive, const T &highInclusive)
Finds the last occurrence of any element outside the specified range within a span.
Definition: memory_extensions.h:2973
ReadOnlySpan< T > TrimEnd(const ReadOnlySpan< T > &span, const T &trimElement)
Trims specified element from the end of a typed span.
Definition: memory_extensions.h:3358
int32_t LastIndexOfAnyInRange(const ReadOnlySpan< T > &span, const T &lowInclusive, const T &highInclusive)
Finds the last occurrence of any element within the specified range within a span.
Definition: memory_extensions.h:2992
int32_t ToUpperInvariant(const ReadOnlySpan< char16_t > &source, Span< char16_t > &destination)
Converts characters to uppercase using invariant culture.
Span< T > AsSpan(const ArrayPtr< T > &array, int32_t start=0, int32_t length=-1)
Creates a span from an array.
Definition: memory_extensions.h:2052
int32_t IndexOf(const ReadOnlySpan< T > &span, const ReadOnlySpan< T > &value)
Finds the index of a ReadOnlySpan<T> value in another ReadOnlySpan<T>
Definition: memory_extensions.h:2476
void Reverse(Span< T > &span)
Reverses the order of elements in a Span in-place.
Definition: memory_extensions.h:3085
bool ContainsAnyInRange(const ReadOnlySpan< T > &span, const T &lowInclusive, const T &highInclusive)
Checks if a read-only span contains any element within the specified range.
Definition: memory_extensions.h:2347
void CopyTo(const ArrayPtr< T > &source, Span< T > &destination)
Copies elements from an array to a span.
Definition: memory_extensions.h:2373
bool StartsWith(const ReadOnlySpan< T > &span, const T &value)
Checks if the span starts with the specified value.
Definition: memory_extensions.h:3253
void Replace(Span< T > &span, const T &oldValue, const T &newValue)
Replaces all occurrences of a value with a new value in a Span.
Definition: memory_extensions.h:3052
bool ContainsAnyExceptInRange(const ReadOnlySpan< T > &span, const T &lowInclusive, const T &highInclusive)
Checks if a read-only span contains any element outside the specified range.
Definition: memory_extensions.h:2321
bool Equals(const ReadOnlySpan< char16_t > &span, const ReadOnlySpan< char16_t > &other, StringComparison comparisonType)
Compares two ReadOnlySpan<char16_t> for equality using StringComparison.
int32_t ToLower(const ReadOnlySpan< char16_t > &source, Span< char16_t > &destination, const SharedPtr< Globalization::CultureInfo > &culture)
Converts characters to lowercase using specified culture.
int32_t LastIndexOfAnyExcept(const ReadOnlySpan< T > &span, const T &value0, const T &value1, const T &value2)
Finds the last occurrence of any element except three specified values within a span.
Definition: memory_extensions.h:2877
ReadOnlyMemory< char16_t > AsMemory(const System::String &text)
Creates a read-only memory from a string.
int32_t IndexOfAnyExcept(const ReadOnlySpan< T > &span, const T &value)
Finds the index of the first element that is not equal to the specified value in a ReadOnlySpan<T>
Definition: memory_extensions.h:2623
int32_t CommonPrefixLength(const ReadOnlySpan< T > &span, const ReadOnlySpan< T > &other)
Finds the length of the common prefix between two spans.
Definition: memory_extensions.h:2101
bool SequenceEqual(const ReadOnlySpan< T > &first, const ReadOnlySpan< T > &second)
Determines if two ReadOnlySpans contain identical elements in the same order.
Definition: memory_extensions.h:3146
int32_t LastIndexOfAny(const ReadOnlySpan< T > &span, const T &value0, const T &value1, const T &value2)
Finds the last occurrence of any of three specified values within a span.
Definition: memory_extensions.h:2810
int32_t IndexOfAnyExceptInRange(const ReadOnlySpan< T > &span, const T &lowInclusive, const T &highInclusive)
Finds the index of the first element that is outside the specified range in a ReadOnlySpan<T>
Definition: memory_extensions.h:2709
bool ContainsAny(const ReadOnlySpan< T > &span, const T &value0, const T &value1)
Checks if a read-only span contains any of two values.
Definition: memory_extensions.h:2185
bool EndsWith(const ReadOnlySpan< T > &span, const T &value)
Determines if a ReadOnlySpan<T> ends with a single value.
Definition: memory_extensions.h:2429
ReadOnlySpan< T > Trim(const ReadOnlySpan< T > &span, T trimElement)
Trims specified element from both ends of a typed span.
Definition: memory_extensions.h:3294
void Sort(const Span< T > &span, const SharedPtr< TComparer > &comparer)
Sorts a Span using a custom comparer.
Definition: memory_extensions.h:3197
int32_t CompareTo(const ReadOnlySpan< char16_t > &span, const ReadOnlySpan< char16_t > &other, StringComparison comparisonType)
Compares two character spans with specified string comparison rules.
bool ContainsAnyExcept(const ReadOnlySpan< T > &span, const T &value0, const T &value1, const T &value2)
Checks if a read-only span contains any element except three specified values.
Definition: memory_extensions.h:2228
int32_t Count(const ReadOnlySpan< T > &span, const T &value)
Counts occurrences of a value in a read-only span.
Definition: memory_extensions.h:2379
int32_t ToUpper(const ReadOnlySpan< char16_t > &source, Span< char16_t > &destination, const SharedPtr< Globalization::CultureInfo > &culture)
Converts characters to uppercase using specified culture.
int32_t LastIndexOf(const ReadOnlySpan< T > &span, const ReadOnlySpan< T > &value)
Finds the last occurrence of a sequence within a span.
Definition: memory_extensions.h:2748
ReadOnlySpan< T > TrimStart(const ReadOnlySpan< T > &span, const T &trimElement)
Trims specified element from the start of a typed span.
Definition: memory_extensions.h:3402
bool Contains(const ReadOnlySpan< T > &span, const T &value)
Checks if a read-only span contains a specific value.
Definition: memory_extensions.h:2172
int32_t IndexOfAnyInRange(const ReadOnlySpan< T > &span, const T &lowInclusive, const T &highInclusive)
Finds the index of the first element that is within the specified range in a ReadOnlySpan<T>
Definition: memory_extensions.h:2728
bool IsWhiteSpace(const ReadOnlySpan< char16_t > &span)
Checks if the entire span consists only of whitespace characters.
int32_t ToLowerInvariant(const ReadOnlySpan< char16_t > &source, Span< char16_t > &destination)
Converts characters to lowercase using invariant culture.
Definition: db_command.h:9
std::enable_if_t<!std::is_floating_point< TA >::value &&!std::is_floating_point< TB >::value, int > Compare(const TA &a, const TB &b)
Compares two values.
Definition: primitive_types.h:113
StringComparison
Defines string comparison style.
Definition: string_comparison.h:13