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/span.h>
8#include <system/object.h>
9#include <system/object_ext.h>
10#include <system/details/stack_array.h>
11#include <system/smart_ptr.h>
12#include <system/exceptions.h>
13#include <system/comparison.h>
14
15namespace System {
16
18namespace MemoryExtensions {
19namespace Details {
21extern ASPOSECPP_SHARED_API const std::array<char16_t, 22> DefaultWhitespaceChars;
22
24extern ASPOSECPP_SHARED_API const ReadOnlySpan<char16_t> DefaultWhitespaceSpan;
25
32template <typename T, typename U>
33int32_t Compare(const SharedPtr<T>& a, const SharedPtr<U>& b)
34{
35 if (!a && !b)
36 {
37 return 0;
38 }
39 if (!a)
40 {
41 return -1;
42 }
43 if (!b)
44 {
45 return 1;
46 }
47 // assume T implements IComparable<Ptr<U>>
48 return (*a).CompareTo(b);
49}
50
56template <typename T>
57int32_t // typename std::enable_if<std::is_arithmetic<T>::value, int32_t>::type
58 Compare(const T& a, const T& b)
59{
60 return System::Compare(a, b);
61}
62
69template <typename T, typename U>
70int32_t Compare(const SharedPtr<T>& a, const U& b)
71{
72 // assume T implements IComparable<U>
73 return (*a).CompareTo(b);
74}
75
82template <typename T>
83int32_t LastIndexOfImpl(const ReadOnlySpan<T>& searchSpace, int32_t length, const T& value)
84{
85 // TODO if value is null find null
86 if (length < 0)
87 return -1;
88
89 while (length >= 8)
90 {
91 length -= 8;
92 if (System::ObjectExt::Equals(value, searchSpace.get(length + 7)))
93 return length + 7;
94 if (System::ObjectExt::Equals(value, searchSpace.get(length + 6)))
95 return length + 6;
96 if (System::ObjectExt::Equals(value, searchSpace.get(length + 5)))
97 return length + 5;
98 if (System::ObjectExt::Equals(value, searchSpace.get(length + 4)))
99 return length + 4;
100 if (System::ObjectExt::Equals(value, searchSpace.get(length + 3)))
101 return length + 3;
102 if (System::ObjectExt::Equals(value, searchSpace.get(length + 2)))
103 return length + 2;
104 if (System::ObjectExt::Equals(value, searchSpace.get(length + 1)))
105 return length + 1;
106 if (System::ObjectExt::Equals(value, searchSpace.get(length)))
107 return length;
108 }
109
110 while (length > 0)
111 {
112 length--;
113 if (System::ObjectExt::Equals(value, searchSpace.get(length)))
114 {
115 return length;
116 }
117 }
118
119 return -1;
120}
121
129template <typename T>
130bool SequenceEqualImpl(const ReadOnlySpan<T>& first, const int32_t start, int32_t length, const ReadOnlySpan<T>& second)
131{
132 int32_t index = 0;
133
134 // Process 8 elements at a time
135 while (length >= 8)
136 {
137 if (!(System::ObjectExt::Equals(first.get(index + start), second.get(index))) ||
138 !(System::ObjectExt::Equals(first.get(index + start + 1), second.get(index + 1))) ||
139 !(System::ObjectExt::Equals(first.get(index + start + 2), second.get(index + 2))) ||
140 !(System::ObjectExt::Equals(first.get(index + start + 3), second.get(index + 3))) ||
141 !(System::ObjectExt::Equals(first.get(index + start + 4), second.get(index + 4))) ||
142 !(System::ObjectExt::Equals(first.get(index + start + 5), second.get(index + 5))) ||
143 !(System::ObjectExt::Equals(first.get(index + start + 6), second.get(index + 6))) ||
144 !(System::ObjectExt::Equals(first.get(index + start + 7), second.get(index + 7))))
145 {
146 return false;
147 }
148
149 index += 8;
150 length -= 8;
151 }
152
153 // Process remaining elements one by one
154 while (length > 0)
155 {
156 if (!(System::ObjectExt::Equals(first.get(index + start), second.get(index))))
157 {
158 return false;
159 }
160 index++;
161 length--;
162 }
163 return true;
164}
165
173template <typename TKey, typename TValue>
174void IntroSort(Span<TKey>& keys, Span<TValue>& values, int32_t depthLimit,
175 std::function<int32_t(const TKey&, const TKey&)> comparer)
176{
177 int32_t partitionSize = keys.get_Length();
178 while (partitionSize > 1)
179 {
180 if (partitionSize <= 16)
181 { // IntrosortSizeThreshold = 16
182 if (partitionSize == 2)
183 {
184 SwapIfGreaterWithValues(keys, values, comparer, 0, 1);
185 return;
186 }
187
188 if (partitionSize == 3)
189 {
190 SwapIfGreaterWithValues(keys, values, comparer, 0, 1);
191 SwapIfGreaterWithValues(keys, values, comparer, 0, 2);
192 SwapIfGreaterWithValues(keys, values, comparer, 1, 2);
193 return;
194 }
195
196 InsertionSort(keys, values, comparer);
197 return;
198 }
199
200 if (depthLimit == 0)
201 {
202 HeapSort(keys, values, comparer);
203 return;
204 }
205 depthLimit--;
206
207 int32_t p = PickPivotAndPartition(keys, values, comparer);
208
209 // Handle the case where pivot is at the end
210 int32_t rightSize = partitionSize - p - 1;
211 if (rightSize > 0)
212 {
213 IntroSort(keys.Slice(p + 1, rightSize), values.Slice(p + 1, rightSize), depthLimit, comparer);
214 }
215
216 // Handle the case where pivot is at the beginning
217 partitionSize = p;
218 }
219}
220
229template <typename TKey, typename TValue>
231 std::function<int32_t(const TKey&, const TKey&)> comparer, int32_t i, int32_t j)
232{
233 if (comparer(keys.get(i), keys.get(j)) > 0)
234 {
235 std::swap(keys.get(i), keys.get(j));
236 std::swap(values.get(i), values.get(j));
237 }
238}
239
246template <typename TKey, typename TValue>
247void InsertionSort(Span<TKey>& keys, Span<TValue>& values, std::function<int32_t(const TKey&, const TKey&)> comparer)
248{
249 for (int32_t i = 0; i < keys.get_Length() - 1; i++)
250 {
251 TKey t = keys.get(i + 1);
252 TValue tValue = values.get(i + 1);
253
254 int32_t j = i;
255 while (j >= 0 && keys.get(j) != t && !comparer(t, keys.get(j)))
256 {
257 keys.get(j + 1) = keys.get(j);
258 values.get(j + 1) = values.get(j);
259 j--;
260 }
261
262 keys.get(j + 1) = t;
263 values.get(j + 1) = tValue;
264 }
265}
266
273template <typename TKey, typename TValue>
274void HeapSort(Span<TKey>& keys, Span<TValue>& values, std::function<int32_t(const TKey&, const TKey&)> comparer)
275{
276 // Build max heap
277 for (int32_t i = keys.get_Length() / 2 - 1; i >= 0; i--)
278 {
279 Heapify(keys, values, keys.get_Length(), i, comparer);
280 }
281
282 // Extract elements from heap one by one
283 for (int32_t i = keys.get_Length() - 1; i > 0; i--)
284 {
285 std::swap(keys.get(0), keys.get(i));
286 std::swap(values.get(0), values.get(i));
287 Heapify(keys, values, i, 0, comparer);
288 }
289}
290
299template <typename TKey, typename TValue>
300void Heapify(Span<TKey>& keys, Span<TValue>& values, int32_t n, int32_t i,
301 std::function<int32_t(const TKey&, const TKey&)> comparer)
302{
303 int32_t largest = i;
304 int32_t left = 2 * i + 1;
305 int32_t right = 2 * i + 2;
306
307 if (left < n && comparer(keys.get(left), keys.get(largest)) > 0)
308 {
309 largest = left;
310 }
311
312 if (right < n && comparer(keys.get(right), keys.get(largest)) > 0)
313 {
314 largest = right;
315 }
316
317 if (largest != i)
318 {
319 std::swap(keys.get(i), keys.get(largest));
320 std::swap(values.get(i), values.get(largest));
321 Heapify(keys, values, n, largest, comparer);
322 }
323}
324
332template <typename TKey, typename TValue>
334 std::function<int32_t(const TKey&, const TKey&)> comparer)
335{
336 // Use median-of-three pivot selection
337 int32_t middle = keys.get_Length() / 2;
338 int32_t last = keys.get_Length() - 1;
339
340 // Sort first, middle, last
341 if (comparer(keys.get(0), keys.get(middle)) > 0)
342 {
343 std::swap(keys.get(0), keys.get(middle));
344 std::swap(values.get(0), values.get(middle));
345 }
346 if (comparer(keys.get(0), keys.get(last)) > 0)
347 {
348 std::swap(keys.get(0), keys.get(last));
349 std::swap(values.get(0), values.get(last));
350 }
351 if (comparer(keys.get(middle), keys.get(last)) > 0)
352 {
353 std::swap(keys.get(middle), keys.get(last));
354 std::swap(values.get(middle), values.get(last));
355 }
356
357 // Place pivot at last position
358 std::swap(keys.get(middle), keys.get(last));
359 std::swap(values.get(middle), values.get(last));
360
361 TKey pivot = keys.get(last);
362 int32_t i = -1;
363
364 for (int32_t j = 0; j < last; j++)
365 {
366 if (comparer(keys.get(j), pivot) <= 0)
367 {
368 i++;
369 std::swap(keys.get(i), keys.get(j));
370 std::swap(values.get(i), values.get(j));
371 }
372 }
373
374 std::swap(keys.get(i + 1), keys.get(last));
375 std::swap(values.get(i + 1), values.get(last));
376 return i + 1;
377}
378
387template <typename T, typename TValue, typename TCompareFunc>
388int32_t BinarySearchImpl(const ReadOnlySpan<T>& span, const TValue& value, TCompareFunc compareFunc)
389{
390 int32_t lo = 0;
391 int32_t hi = span.get_Length() - 1;
392
393 while (lo <= hi)
394 {
395 // Safe unsigned arithmetic to avoid overflow
396 int32_t i = static_cast<int32_t>((static_cast<uint32_t>(hi) + static_cast<uint32_t>(lo)) >> 1);
397 int32_t c = compareFunc(value, span.get(i));
398 if (c == 0)
399 {
400 return i;
401 }
402 else if (c > 0)
403 {
404 lo = i + 1;
405 }
406 else
407 {
408 hi = i - 1;
409 }
410 }
411
412 return ~lo;
413}
414
415} // namespace Details
416
422ASPOSECPP_SHARED_API ReadOnlySpan<char16_t> AsSpan(const String& text, int32_t start = 0, int32_t length = -1);
423
430template <typename T>
431Span<T> AsSpan(const ArrayPtr<T>& array, int32_t start = 0, int32_t length = -1)
432{
433 if (array == nullptr)
434 {
435 throw ArgumentNullException(u"array is null");
436 }
437 if (start < 0 || (length < 0 && length != -1) ||
438 (length == -1 ? start > array->get_Length() : start + length > array->get_Length()))
439 {
440 throw ArgumentOutOfRangeException(u"start or length is out of range");
441 }
442 if (length == -1)
443 {
444 length = array->get_Length() - start;
445 }
446 return Span<T>(array, start, length);
447}
448
455template <typename T, typename TComparable>
456int32_t BinarySearch(const ReadOnlySpan<T>& span, const TComparable& comparable)
457{
458 return Details::BinarySearchImpl(span, comparable,
459 [](const TComparable& search_value, const T& container_value) -> int32_t {
460 return Details::Compare(search_value, container_value);
461 });
462}
463
471template <typename T, typename TComparer>
472int32_t BinarySearch(const ReadOnlySpan<T>& span, const T& value, const SharedPtr<TComparer>& comparerPtr)
473{
474 return Details::BinarySearchImpl(span, value,
475 [&comparerPtr](const T& search_value, const T& container_value) -> int32_t {
476 return comparerPtr->Compare(search_value, container_value);
477 });
478}
479
486template <typename T, typename TComparable>
487int32_t BinarySearch(const Span<T>& span, const TComparable& comparable)
488{
489 return BinarySearch(static_cast<ReadOnlySpan<T>>(span), comparable);
490}
491
499template <typename T, typename TComparer>
500int32_t BinarySearch(const Span<T>& span, const T& value, const SharedPtr<TComparer>& comparer)
501{
502 return BinarySearch(static_cast<ReadOnlySpan<T>>(span), value, comparer);
503}
504
510template <typename T>
511int32_t CommonPrefixLength(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other)
512{
513 int32_t commonLength = 0;
514 int32_t minLength = std::min(span.get_Length(), other.get_Length());
515
516 // Compare elements until a mismatch is found
517 for (int32_t i = 0; i < minLength; ++i)
518 {
519 if (System::ObjectExt::Equals(span.get(i), other.get(i)))
520 {
521 ++commonLength;
522 }
523 else
524 {
525 break; // Mismatch found, exit early
526 }
527 }
528
529 return commonLength;
530}
531
537template <typename T>
538int32_t CommonPrefixLength(const Span<T>& span, const ReadOnlySpan<T>& other)
539{
540 return CommonPrefixLength(static_cast<ReadOnlySpan<T>>(span), other);
541}
542
548template <typename T>
549int32_t CommonPrefixLength(const Span<T>& span, const Span<T>& other)
550{
551 return CommonPrefixLength(static_cast<ReadOnlySpan<T>>(span), static_cast<ReadOnlySpan<T>>(other));
552}
553
561template <typename T, typename TEqualityComparer>
562int32_t CommonPrefixLength(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other,
563 const SharedPtr<TEqualityComparer>& comparer)
564{
565 int32_t commonLength = 0;
566 int32_t minLength = std::min(span.get_Length(), other.get_Length());
567
568 // Compare elements until a mismatch is found
569 for (int32_t i = 0; i < minLength; ++i)
570 {
571 if ((comparer == nullptr && System::ObjectExt::Equals(span.get(i), other.get(i))) ||
572 (comparer != nullptr && comparer->Equals(span.get(i), other.get(i))))
573 {
574 ++commonLength;
575 }
576 else
577 {
578 break; // Mismatch found, exit early
579 }
580 }
581
582 return commonLength;
583}
584
593template <typename T, typename TEqualityComparer>
594int32_t CommonPrefixLength(const Span<T>& span, const ReadOnlySpan<T>& other,
595 const SharedPtr<TEqualityComparer>& comparer)
596{
597 return CommonPrefixLength(static_cast<ReadOnlySpan<T>>(span), other, comparer);
598}
599
607template <typename T, typename TEqualityComparer>
608int32_t CommonPrefixLength(const Span<T>& span, const Span<T>& other, const SharedPtr<TEqualityComparer>& comparer)
609{
610 return CommonPrefixLength(static_cast<ReadOnlySpan<T>>(span), static_cast<ReadOnlySpan<T>>(other), comparer);
611}
612
618ASPOSECPP_SHARED_API int32_t CompareTo(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& other,
619 StringComparison comparisonType);
620
626ASPOSECPP_SHARED_API bool Contains(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& value,
627 StringComparison comparisonType);
628
629
630
636template <typename T>
637bool Contains(const ReadOnlySpan<T>& span, const T& value)
638{
639 return std::find_if(span.begin(), span.end(), [&value](const T& item) { return System::ObjectExt::Equals(value, item); }) !=
640 span.end();
641}
642
648template <typename T>
649bool Contains(const Span<T>& span, const T& value)
650{
651 return std::find(span.begin(), span.end(), value) != span.end();
652}
653
660template <typename T>
661bool ContainsAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
662{
663 return Contains(span, value0) || Contains(span, value1);
664}
665
673template <typename T>
674bool ContainsAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
675{
676 return Contains(span, value0) || Contains(span, value1) || Contains(span, value2);
677}
678
685template <typename T>
686bool ContainsAny(const Span<T>& span, const T& value0, const T& value1)
687{
688 return ContainsAny(static_cast<const ReadOnlySpan<T>&>(span), value0, value1);
689}
690
698template <typename T>
699bool ContainsAny(const Span<T>& span, const T& value0, const T& value1, const T& value2)
700{
701 return ContainsAny(static_cast<const ReadOnlySpan<T>&>(span), value0, value1, value2);
702}
703
709template <typename T>
710bool ContainsAny(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
711{
712 for (const auto& value : values)
713 {
714 if (Contains(span, value))
715 {
716 return true; // Found at least one value
717 }
718 }
719 return false; // Not found
720}
721
727template <typename T>
728bool ContainsAny(const Span<T>& span, const ReadOnlySpan<T>& values)
729{
730 return ContainsAny(static_cast<const ReadOnlySpan<T>&>(span), values);
731}
732
740template <typename T>
741bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
742{
743 for (auto& member : span)
744 {
745 if (!System::ObjectExt::Equals(member, value0) && !System::ObjectExt::Equals(member, value1) &&
746 !System::ObjectExt::Equals(member, value2))
747 {
748 return true;
749 }
750 }
751 return false;
752}
753
761template <typename T>
762bool ContainsAnyExcept(const Span<T>& span, const T& value0, const T& value1, const T& value2)
763{
764 return ContainsAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value0, value1, value2);
765}
766
773template <typename T>
774bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
775{
776 for (auto& member : span)
777 {
778 if (!System::ObjectExt::Equals(member, value0) && !System::ObjectExt::Equals(member, value1))
779 {
780 return true;
781 }
782 }
783 return false;
784}
785
792template <typename T>
793bool ContainsAnyExcept(const Span<T>& span, const T& value0, const T& value1)
794{
795 return ContainsAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value0, value1);
796}
797
803template <typename T>
804bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const T& value)
805{
806 for (auto& member : span)
807 {
808 if (!System::ObjectExt::Equals(member, value))
809 {
810 return true;
811 }
812 }
813 return false;
814}
815
821template <typename T>
822bool ContainsAnyExcept(const Span<T>& span, const T& value)
823{
824 return ContainsAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value);
825}
826
832template <typename T>
833bool ContainsAnyExcept(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
834{
835 switch (values.get_Length())
836 {
837 case 0:
838 return span.get_IsEmpty() ? false : true;
839
840 case 1:
841 return ContainsAnyExcept(span, values.get(0));
842
843 case 2:
844 return ContainsAnyExcept(span, values.get(0), values.get(1));
845
846 case 3:
847 return ContainsAnyExcept(span, values.get(0), values.get(1), values.get(2));
848
849 default:
850 for (auto& member : span)
851 {
852 if (!Contains(values, member))
853 {
854 return true;
855 }
856 }
857 return false;
858 }
859}
860
866template <typename T>
867bool ContainsAnyExcept(const Span<T>& span, const ReadOnlySpan<T>& values)
868{
869 return ContainsAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), values);
870}
871
878template <typename T>
879bool ContainsAnyExceptInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
880{
881 for (const auto& value : span)
882 {
883 if (value < lowInclusive || value > highInclusive)
884 {
885 return true; // Found a value outside the range
886 }
887 }
888 return false; // All values are within the range
889}
890
897template <typename T>
898bool ContainsAnyExceptInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
899{
900 for (const auto& value : span)
901 {
902 if (value < lowInclusive || value > highInclusive)
903 {
904 return true; // Found a value outside the range
905 }
906 }
907 return false; // All values are within the range
908}
909
916template <typename T>
917bool ContainsAnyInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
918{
919 for (const auto& value : span)
920 {
921 if (value >= lowInclusive && value <= highInclusive)
922 {
923 return true; // Found a value within the range
924 }
925 }
926 return false; // No values found within the range
927}
928
935template <typename T>
936bool ContainsAnyInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
937{
938 for (const auto& value : span)
939 {
940 if (value >= lowInclusive && value <= highInclusive)
941 {
942 return true; // Found a value within the range
943 }
944 }
945 return false; // No values found within the range
946}
947
952template <typename T>
953void CopyTo(const ArrayPtr<T>& source, Span<T>& destination)
954{
955 return ReadOnlySpan<T>(source).CopyTo(destination);
956}
957
963template <typename T>
964int32_t Count(const ReadOnlySpan<T>& span, const T& value)
965{
966 int32_t count = 0;
967 for (const auto& item : span)
968 {
969 if (System::ObjectExt::Equals(item, value))
970 {
971 ++count;
972 }
973 }
974 return count;
975}
976
982template <typename T>
983int32_t Count(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value)
984{
985 switch (value.get_Length())
986 {
987 case 0:
988 return 0;
989
990 case 1:
991 return Count(span, value.get(0));
992
993 default:
994 int32_t count = 0;
995 int32_t pos = 0;
996 ReadOnlySpan<T> currentSpan = span;
997 while ((pos = IndexOf(currentSpan, value)) >= 0)
998 {
999 count++;
1000 currentSpan = currentSpan.Slice(pos + value.get_Length());
1001 }
1002 return count;
1003 }
1004}
1005
1011template <typename T>
1012int32_t Count(const Span<T>& span, const T& value)
1013{
1014 return Count(ReadOnlySpan<T>(span), value); // Delegate to ReadOnlySpan<T> method
1015}
1016
1022template <typename T>
1023int32_t Count(const Span<T>& span, const ReadOnlySpan<T>& value)
1024{
1025 return Count(ReadOnlySpan<T>(span), value); // Delegate to ReadOnlySpan<T> method
1026}
1027
1033ASPOSECPP_SHARED_API bool EndsWith(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& value,
1034 StringComparison comparisonType);
1035
1041template <typename T>
1042bool EndsWith(const ReadOnlySpan<T>& span, const T& value)
1043{
1044 if (span.get_Length() == 0)
1045 {
1046 return false; // Empty span does not end with any value
1047 }
1048 return System::ObjectExt::Equals(span.get(span.get_Length() - 1), value);
1049}
1050
1056template <typename T>
1057bool EndsWith(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value)
1058{
1059 int32_t spanLength = span.get_Length();
1060 int32_t valueLength = value.get_Length();
1061
1062 if (valueLength > spanLength)
1063 {
1064 return false;
1065 }
1066
1067 if (valueLength == spanLength)
1068 {
1069 return SequenceEqual(span, value);
1070 }
1071
1072 return SequenceEqual(span.Slice(spanLength - valueLength), value);
1073}
1074
1080template <typename T>
1081bool EndsWith(const Span<T>& span, const ReadOnlySpan<T>& value)
1082{
1083 return EndsWith(ReadOnlySpan<T>(span), value);
1084}
1085
1091template <typename T>
1092bool EndsWith(const ReadOnlySpan<T>& span, const Span<T>& value)
1093{
1094 return EndsWith(span, ReadOnlySpan<T>(value));
1095}
1096
1102template <typename T>
1103bool EndsWith(const Span<T>& span, const Span<T>& value)
1104{
1105 return EndsWith(ReadOnlySpan<T>(span), ReadOnlySpan<T>(value));
1106}
1107
1113ASPOSECPP_SHARED_API bool Equals(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& other,
1114 StringComparison comparisonType);
1115
1121ASPOSECPP_SHARED_API int32_t IndexOf(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& value,
1122 StringComparison comparisonType);
1123
1129template <typename T>
1130int32_t IndexOf(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value)
1131{
1132 if (value.get_Length() == 0)
1133 {
1134 return 0; // A zero-length sequence is always treated as "found" at the start of the search space.
1135 }
1136
1137 const T& valueHead = value.get(0);
1138 int32_t valueTailLength = value.get_Length() - 1;
1139
1140 int32_t index = 0;
1141 while (true)
1142 {
1143 if (index + valueTailLength > span.get_Length())
1144 {
1145 break; // The unsearched portion is now shorter than the sequence we're looking for.
1146 }
1147
1148 // Search for the first element of "value".
1149 int32_t remainingSearchSpaceLength = span.get_Length() - index - valueTailLength;
1150 int32_t relativeIndex = -1; // Default to not found
1151
1152 for (int32_t i = 0; i < remainingSearchSpaceLength; ++i)
1153 {
1154 if (System::ObjectExt::Equals(span.get(index + i), valueHead))
1155 {
1156 relativeIndex = i;
1157 break;
1158 }
1159 }
1160
1161 if (relativeIndex == -1)
1162 {
1163 break; // First element not found.
1164 }
1165
1166 index += relativeIndex;
1167
1168 // Found the first element of "value". Check if the tail matches.
1169 bool tailMatches = true;
1170 for (int32_t i = 0; i < valueTailLength; ++i)
1171 {
1172 if (span.get(index + 1 + i) != value.get(1 + i))
1173 {
1174 tailMatches = false;
1175 break;
1176 }
1177 }
1178
1179 if (tailMatches)
1180 {
1181 return index; // The tail matched. Return a successful find.
1182 }
1183
1184 ++index; // Move to the next position in the search space.
1185 }
1186
1187 return -1; // Not found.
1188}
1189
1195template <typename T>
1196int32_t IndexOf(const ReadOnlySpan<T>& span, const T& value)
1197{
1198 for (int32_t i = 0; i < span.get_Length(); ++i)
1199 {
1200 if (System::ObjectExt::Equals(span.get(i), value))
1201 {
1202 return i; // Found
1203 }
1204 }
1205 return -1; // Not found
1206}
1207
1213template <typename T>
1214int32_t IndexOf(const Span<T>& span, const ReadOnlySpan<T>& value)
1215{
1216 return IndexOf(static_cast<ReadOnlySpan<T>>(span), value);
1217}
1218
1224template <typename T>
1225int32_t IndexOf(const Span<T>& span, const T& value)
1226{
1227 return IndexOf(static_cast<ReadOnlySpan<T>>(span), value);
1228}
1229
1236template <typename T>
1237int32_t IndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
1238{
1239 for (int32_t i = 0; i < span.get_Length(); ++i)
1240 {
1241 if (System::ObjectExt::Equals(span.get(i), value0) || System::ObjectExt::Equals(span.get(i), value1))
1242 {
1243 return i; // Found
1244 }
1245 }
1246 return -1; // Not found
1247}
1248
1256template <typename T>
1257int32_t IndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
1258{
1259 for (int32_t i = 0; i < span.get_Length(); ++i)
1260 {
1261 if (System::ObjectExt::Equals(span.get(i), value0) || System::ObjectExt::Equals(span.get(i), value1) ||
1262 System::ObjectExt::Equals(span.get(i), value2))
1263 {
1264 return i; // Found
1265 }
1266 }
1267 return -1; // Not found
1268}
1269
1276template <typename T>
1277int32_t IndexOfAny(const Span<T>& span, const T& value0, const T& value1)
1278{
1279 return IndexOfAny(static_cast<ReadOnlySpan<T>>(span), value0, value1);
1280}
1281
1289template <typename T>
1290int32_t IndexOfAny(const Span<T>& span, const T& value0, const T& value1, const T& value2)
1291{
1292 return IndexOfAny(static_cast<ReadOnlySpan<T>>(span), value0, value1, value2);
1293}
1294
1300template <typename T>
1301int32_t IndexOfAny(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
1302{
1303 for (int32_t i = 0; i < span.get_Length(); ++i)
1304 {
1305 for (int32_t j = 0; j < values.get_Length(); ++j)
1306 {
1307 if (System::ObjectExt::Equals(span.get(i), values.get(j)))
1308 {
1309 return i; // Found
1310 }
1311 }
1312 }
1313 return -1; // Not found
1314}
1315
1321template <typename T>
1322int32_t IndexOfAny(const Span<T>& span, const ReadOnlySpan<T>& values)
1323{
1324 return IndexOfAny(static_cast<ReadOnlySpan<T>>(span), values);
1325}
1326
1332template <typename T>
1333int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value)
1334{
1335 for (int32_t i = 0; i < span.get_Length(); ++i)
1336 {
1337 if (!System::ObjectExt::Equals(span.get(i), value))
1338 {
1339 return i; // Found
1340 }
1341 }
1342 return -1; // Not found
1343}
1344
1352template <typename T>
1353int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
1354{
1355 for (int32_t i = 0; i < span.get_Length(); ++i)
1356 {
1357 if (!System::ObjectExt::Equals(span.get(i), value0) && !System::ObjectExt::Equals(span.get(i), value1))
1358 {
1359 return i; // Found
1360 }
1361 }
1362 return -1; // Not found
1363}
1364
1373template <typename T>
1374int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
1375{
1376 for (int32_t i = 0; i < span.get_Length(); ++i)
1377 {
1378 if (!System::ObjectExt::Equals(span.get(i), value0) && !System::ObjectExt::Equals(span.get(i), value1) &&
1379 !System::ObjectExt::Equals(span.get(i), value2))
1380 {
1381 return i; // Found
1382 }
1383 }
1384 return -1; // Not found
1385}
1386
1392template <typename T>
1393int32_t IndexOfAnyExcept(const Span<T>& span, const T& value)
1394{
1395 return IndexOfAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value);
1396}
1397
1404template <typename T>
1405int32_t IndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1)
1406{
1407 return IndexOfAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value0, value1);
1408}
1409
1417template <typename T>
1418int32_t IndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1, const T& value2)
1419{
1420 return IndexOfAnyExcept(static_cast<const ReadOnlySpan<T>&>(span), value0, value1, value2);
1421}
1422
1428template <typename T>
1429int32_t IndexOfAnyExcept(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
1430{
1431 for (int32_t i = 0; i < span.get_Length(); ++i)
1432 {
1433 bool found = false;
1434 for (int32_t j = 0; j < values.get_Length(); ++j)
1435 {
1436 if (System::ObjectExt::Equals(span.get(i), values.get(j)))
1437 {
1438 found = true;
1439 break;
1440 }
1441 }
1442 if (!found)
1443 {
1444 return i; // Found
1445 }
1446 }
1447 return -1; // Not found
1448}
1449
1455template <typename T>
1456int32_t IndexOfAnyExcept(const Span<T>& span, const ReadOnlySpan<T>& values)
1457{
1458 return IndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), values);
1459}
1460
1467template <typename T>
1468int32_t IndexOfAnyExceptInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
1469{
1470 for (int32_t i = 0; i < span.get_Length(); ++i)
1471 {
1472 if (Details::Compare(span.get(i), lowInclusive) < 0 || Details::Compare(span.get(i), highInclusive) > 0)
1473 {
1474 return i; // Found an element outside the range
1475 }
1476 }
1477 return -1; // Not found
1478}
1479
1486template <typename T>
1487int32_t IndexOfAnyExceptInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
1488{
1489 return IndexOfAnyExceptInRange(static_cast<const ReadOnlySpan<T>&>(span), lowInclusive, highInclusive);
1490}
1491
1498template <typename T>
1499int32_t IndexOfAnyInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
1500{
1501 for (int32_t i = 0; i < span.get_Length(); ++i)
1502 {
1503 // if (span.get(i).CompareTo(lowInclusive) >= 0 && span.get(i).CompareTo(highInclusive) <= 0) {
1504 if (Details::Compare(span.get(i), lowInclusive) >= 0 && Details::Compare(span.get(i), highInclusive) <= 0)
1505 {
1506 return i; // Found an element within the range
1507 }
1508 }
1509 return -1; // Not found
1510}
1511
1518template <typename T>
1519int32_t IndexOfAnyInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
1520{
1521 return IndexOfAnyInRange(static_cast<const ReadOnlySpan<T>&>(span), lowInclusive, highInclusive);
1522}
1523
1527ASPOSECPP_SHARED_API bool IsWhiteSpace(const ReadOnlySpan<char16_t>& span);
1528
1534ASPOSECPP_SHARED_API int32_t LastIndexOf(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& value,
1535 StringComparison comparisonType);
1536
1542template <typename T>
1543int32_t LastIndexOf(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value)
1544{
1545 if (value.get_Length() == 0)
1546 return span.get_Length(); // A zero-length sequence is always treated as "found" at the end of the search space.
1547
1548 int32_t valueTailLength = value.get_Length() - 1;
1549 if (valueTailLength == 0)
1550 {
1551 return LastIndexOf<T>(span, value.get(0));
1552 }
1553
1554 int32_t index = 0;
1555
1556 T valueHead = value.get(0);
1557 ReadOnlySpan<T> valueTail = value.Slice(1);
1558
1559 while (true)
1560 {
1561 int32_t remainingSearchSpaceLength = span.get_Length() - index - valueTail.get_Length(); // отступ
1562 if (remainingSearchSpaceLength <= 0)
1563 break;
1564
1565 // Do a quick search for the first element of "value".
1566 int32_t relativeIndex = Details::LastIndexOfImpl<T>(span, remainingSearchSpaceLength, valueHead);
1567 if (relativeIndex < 0)
1568 break;
1569
1570 // Found the first element of "value". See if the tail matches.
1571 if (Details::SequenceEqualImpl<T>(span, relativeIndex + 1, valueTail.get_Length(), valueTail))
1572 return relativeIndex;
1573
1574 index += remainingSearchSpaceLength - relativeIndex;
1575 }
1576 return -1;
1577}
1578
1584template <typename T>
1585int32_t LastIndexOf(const ReadOnlySpan<T>& span, const T& value)
1586{
1587 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
1588 {
1589 if (System::ObjectExt::Equals(span.get(i), value))
1590 {
1591 return i; // Found
1592 }
1593 }
1594 return -1; // Not found
1595}
1596
1602template <typename T>
1603int32_t LastIndexOf(const Span<T>& span, const ReadOnlySpan<T>& value)
1604{
1605 return LastIndexOf(static_cast<const ReadOnlySpan<T>&>(span), value); // Cast for use with ReadOnlySpan
1606}
1607
1613template <typename T>
1614int32_t LastIndexOf(const Span<T>& span, const T& value)
1615{
1616 return LastIndexOf(static_cast<const ReadOnlySpan<T>&>(span), value); // Cast for use with ReadOnlySpan
1617}
1618
1626template <typename T>
1627int32_t LastIndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
1628{
1629 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
1630 {
1631 if (System::ObjectExt::Equals(span.get(i), value0) || System::ObjectExt::Equals(span.get(i), value1) ||
1632 System::ObjectExt::Equals(span.get(i), value2))
1633 {
1634 return i; // Found
1635 }
1636 }
1637 return -1; // Not found
1638}
1639
1647template <typename T>
1648int32_t LastIndexOfAny(const Span<T>& span, const T& value0, const T& value1, const T& value2)
1649{
1650 return LastIndexOfAny(static_cast<const ReadOnlySpan<T>&>(span), value0, value1, value2);
1651}
1652
1659template <typename T>
1660int32_t LastIndexOfAny(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
1661{
1662 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
1663 {
1664 if (System::ObjectExt::Equals(span.get(i), value0) || System::ObjectExt::Equals(span.get(i), value1))
1665 {
1666 return i; // Found
1667 }
1668 }
1669 return -1; // Not found
1670}
1671
1678template <typename T>
1679int32_t LastIndexOfAny(const Span<T>& span, const T& value0, const T& value1)
1680{
1681 return LastIndexOfAny(static_cast<const ReadOnlySpan<T>&>(span), value0, value1);
1682}
1683
1689template <typename T>
1690int32_t LastIndexOfAny(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
1691{
1692 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
1693 {
1694 for (int32_t j = 0; j < values.get_Length(); ++j)
1695 {
1696 if (System::ObjectExt::Equals(span.get(i), values.get(j)))
1697 {
1698 return i; // Found
1699 }
1700 }
1701 }
1702 return -1; // Not found
1703}
1704
1710template <typename T>
1711int32_t LastIndexOfAny(const Span<T>& span, const ReadOnlySpan<T>& values)
1712{
1713 return LastIndexOfAny(static_cast<const ReadOnlySpan<T>&>(span), values);
1714}
1715
1721template <typename T>
1722int32_t LastIndexOfAny(const Span<T>& span, const Span<T>& values)
1723{
1724 return LastIndexOfAny(static_cast<const ReadOnlySpan<T>&>(span), static_cast<const ReadOnlySpan<T>&>(values));
1725}
1726
1734template <typename T>
1735int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1, const T& value2)
1736{
1737 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
1738 {
1739 const T& current = span.get(i);
1740 if (!(System::ObjectExt::Equals(current, value0) || System::ObjectExt::Equals(current, value1) ||
1741 System::ObjectExt::Equals(current, value2)))
1742 {
1743 return i;
1744 }
1745 }
1746 return -1; // Not found
1747}
1748
1756template <typename T>
1757int32_t LastIndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1, const T& value2)
1758{
1759 return LastIndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), value0, value1, value2);
1760}
1761
1768template <typename T>
1769int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value0, const T& value1)
1770{
1771 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
1772 {
1773 const T& current = span.get(i);
1774 if (!(System::ObjectExt::Equals(current, value0) || System::ObjectExt::Equals(current, value1)))
1775 {
1776 return i;
1777 }
1778 }
1779 return -1; // Not found
1780}
1781
1788template <typename T>
1789int32_t LastIndexOfAnyExcept(const Span<T>& span, const T& value0, const T& value1)
1790{
1791 return LastIndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), value0, value1);
1792}
1793
1799template <typename T>
1800int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const T& value)
1801{
1802 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
1803 {
1804 T current = span.get(i);
1805 if (!(System::ObjectExt::Equals(current, value)))
1806 {
1807 return i;
1808 }
1809 }
1810 return -1; // Not found
1811}
1812
1818template <typename T>
1819int32_t LastIndexOfAnyExcept(const Span<T>& span, const T& value)
1820{
1821 return LastIndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), value);
1822}
1823
1829template <typename T>
1830int32_t LastIndexOfAnyExcept(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& values)
1831{
1832 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
1833 {
1834 const T& current = span.get(i);
1835 bool found = false;
1836 for (auto& value : values)
1837 {
1838 if (System::ObjectExt::Equals(current, value))
1839 {
1840 found = true;
1841 break;
1842 }
1843 }
1844 if (!found)
1845 {
1846 return i;
1847 }
1848 }
1849 return -1; // Not found
1850}
1851
1857template <typename T>
1858int32_t LastIndexOfAnyExcept(const Span<T>& span, const ReadOnlySpan<T>& values)
1859{
1860 return LastIndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), values);
1861}
1862
1868template <typename T>
1869int32_t LastIndexOfAnyExcept(const Span<T>& span, const Span<T>& values)
1870{
1871 return LastIndexOfAnyExcept(static_cast<ReadOnlySpan<T>>(span), static_cast<ReadOnlySpan<T>>(values));
1872}
1873
1880template <typename T>
1881int32_t LastIndexOfAnyExceptInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
1882{
1883 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
1884 {
1885 if (Details::Compare(span.get(i), lowInclusive) < 0 || Details::Compare(span.get(i), highInclusive) > 0)
1886 {
1887 return i; // Found an element outside the range
1888 }
1889 }
1890 return -1; // Not found
1891}
1892
1899template <typename T>
1900int32_t LastIndexOfAnyExceptInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
1901{
1902 return LastIndexOfAnyExceptInRange(static_cast<ReadOnlySpan<T>>(span), lowInclusive, highInclusive);
1903}
1904
1911template <typename T>
1912int32_t LastIndexOfAnyInRange(const ReadOnlySpan<T>& span, const T& lowInclusive, const T& highInclusive)
1913{
1914 for (int32_t i = span.get_Length() - 1; i >= 0; --i)
1915 {
1916 if (Details::Compare(span.get(i), lowInclusive) >= 0 && Details::Compare(span.get(i), highInclusive) <= 0)
1917 {
1918 return i; // Found an element outside the range
1919 }
1920 }
1921 return -1; // Not found
1922}
1923
1930template <typename T>
1931int32_t LastIndexOfAnyInRange(const Span<T>& span, const T& lowInclusive, const T& highInclusive)
1932{
1933 return LastIndexOfAnyInRange(static_cast<ReadOnlySpan<T>>(span), lowInclusive, highInclusive);
1934}
1935
1941template <typename T>
1942bool Overlaps(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other)
1943{
1944 int32_t offset;
1945 return Overlaps(span, other, offset);
1946}
1947
1953template <typename T>
1954bool Overlaps(const Span<T>& span, const ReadOnlySpan<T>& other)
1955{
1956 return Overlaps(static_cast<ReadOnlySpan<T>>(span), other);
1957}
1958
1965template <typename T>
1966bool Overlaps(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other, int32_t& elementOffset)
1967{
1968 if (span.get_IsEmpty() || other.get_IsEmpty())
1969 {
1970 elementOffset = 0;
1971 return false;
1972 }
1973 ptrdiff_t Offset = other.begin() - span.begin();
1974 bool isOverlap = (Offset >= 0 && Offset < span.get_Length()) || (Offset < 0 && -Offset < other.get_Length());
1975
1976 if (isOverlap)
1977 {
1978 elementOffset = static_cast<int32_t>(Offset);
1979 }
1980 else
1981 {
1982 elementOffset = 0;
1983 }
1984 return isOverlap;
1985}
1986
1993template <typename T>
1994bool Overlaps(const Span<T>& span, const ReadOnlySpan<T>& other, int32_t& elementOffset)
1995{
1996 return Overlaps(static_cast<ReadOnlySpan<T>>(span), other, elementOffset);
1997}
1998
2004template <typename T>
2005void Replace(Span<T>& span, const T& oldValue, const T& newValue)
2006{
2007 for (int32_t i = 0; i < span.get_Length(); ++i)
2008 {
2009 if (System::ObjectExt::Equals(span.get(i), oldValue))
2010 {
2011 span.get(i) = newValue; // Replace oldValue with newValue
2012 }
2013 }
2014}
2015
2023template <typename T>
2024void Replace(const ReadOnlySpan<T>& source, Span<T>& destination, const T& oldValue, const T& newValue)
2025{
2026 if (destination.get_Length() < source.get_Length())
2027 {
2028 throw ArgumentException(u"Destination span is smaller than source span.");
2029 }
2030
2031 for (int32_t i = 0; i < source.get_Length(); ++i)
2032 {
2033 if (System::ObjectExt::Equals(source.get(i), oldValue))
2034 {
2035 destination.get(i) = newValue; // Replace oldValue with newValue
2036 }
2037 else
2038 {
2039 destination.get(i) = source.get(i); // Copy the original value
2040 }
2041 }
2042}
2043
2047template <typename T>
2048void Reverse(Span<T>& span)
2049{
2050 int32_t left = 0;
2051 int32_t right = span.get_Length() - 1;
2052 while (left < right)
2053 {
2054 std::swap(span.get(left), span.get(right));
2055 ++left;
2056 --right;
2057 }
2058}
2059
2065template <typename T>
2066int32_t SequenceCompareTo(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other)//span.begin() ++
2067{
2068 auto spanIt = span.begin();
2069 auto otherIt = other.begin();
2070 auto spanEnd = span.end();
2071 auto otherEnd = other.end();
2072
2073 while (spanIt != spanEnd && otherIt != otherEnd)
2074 {
2075 if (*spanIt < *otherIt)
2076 {
2077 return -1; // span is less than other
2078 }
2079 if (*spanIt > *otherIt)
2080 {
2081 return 1; // span is greater than other
2082 }
2083
2084 ++spanIt;
2085 ++otherIt;
2086 }
2087
2088 // If all elements are equal up to the length of the shorter span
2089 if (span.get_Length() < other.get_Length())
2090 {
2091 return -1; // span is shorter
2092 }
2093 if (span.get_Length() > other.get_Length())
2094 {
2095 return 1; // span is longer
2096 }
2097
2098 return 0; // spans are equal
2099}
2100
2106template <typename T>
2107int32_t SequenceCompareTo(const Span<T>& span, const ReadOnlySpan<T>& other)
2108{
2109 return SequenceCompareTo(static_cast<ReadOnlySpan<T>>(span), other);
2110}
2111
2117template <typename T>
2118int32_t SequenceCompareTo(const ReadOnlySpan<T>& span, const Span<T>& other)
2119{
2120 return SequenceCompareTo(span, static_cast<ReadOnlySpan<T>>(other));
2121}
2122
2128template <typename T>
2129bool SequenceEqual(const ReadOnlySpan<T>& first, const ReadOnlySpan<T>& second)
2130{
2131 if (first == second)
2132 return true;
2133
2134 if (first.get_Length() != second.get_Length())
2135 {
2136 return false;
2137 }
2138
2139 int32_t length = second.get_Length();
2140
2141 return Details::SequenceEqualImpl(first, 0, first.get_Length(), second);
2142}
2143
2149template <typename T>
2150bool SequenceEqual(const Span<T>& span, const ReadOnlySpan<T>& other)
2151{
2152 return SequenceEqual(static_cast<ReadOnlySpan<T>>(span), other);
2153}
2154
2162template <typename T, typename TComparer>
2163bool SequenceEqual(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& other, SharedPtr<TComparer>& comparer)
2164{
2165 if (comparer == nullptr)
2166 {
2167 return SequenceEqual(span, other);
2168 }
2169
2170 if (span.get_Length() != other.get_Length())
2171 {
2172 return false; // Lengths are not equal
2173 }
2174
2175 for (int32_t i = 0; i < span.get_Length(); ++i)
2176 {
2177 if (!comparer->Equals(span.get(i), other.get(i)))
2178 {
2179 return false; // Elements are not equal
2180 }
2181 }
2182 return true; // All elements are equal
2183}
2184
2192template <typename T, typename TComparer>
2193bool SequenceEqual(const Span<T>& span, const ReadOnlySpan<T>& other, SharedPtr<TComparer>& comparer)
2194{
2195 return SequenceEqual(static_cast<ReadOnlySpan<T>>(span), other, comparer);
2196}
2197
2203template <typename T, typename TComparer>
2204void Sort(const Span<T>& span, const SharedPtr<TComparer>& comparer)
2205{
2206 std::sort(span.begin(), span.end(), [&comparer](const T& a, const T& b) -> bool { return comparer->Compare(a, b) < 0; });
2207}
2208
2212template <typename T>
2213void Sort(Span<T>& span)
2214{
2215 std::sort(span.begin(), span.end());
2216}
2217
2226template <typename TKey, typename TValue, typename TComparer>
2227void Sort(Span<TKey>& keys, Span<TValue>& values, const SharedPtr<TComparer>& comparer)
2228{
2229 if (keys.get_Length() != values.get_Length())
2230 {
2231 throw ArgumentException(u"Keys and items must have the same length.");
2232 }
2233 if (keys.get_Length() > 1)
2234 {
2235 int32_t depthLimit = 2 * (static_cast<int32_t>(std::log2(keys.get_Length())) + 1);
2236 Details::IntroSort<TKey, TValue>(keys, values, depthLimit,
2237 [&comparer](TKey a, TKey b) -> bool { return comparer->Compare(a, b) > 0; });
2238 }
2239}
2240
2248template <typename TKey, typename TValue>
2250{
2251 if (keys.get_Length() != values.get_Length())
2252 {
2253 throw ArgumentException(u"Keys and items must have the same length.");
2254 }
2255 if (keys.get_Length() > 1)
2256 {
2257 int32_t depthLimit = 2 * (static_cast<int32_t>(std::log2(keys.get_Length())) + 1);
2258 Details::IntroSort<TKey, TValue>(keys, values, depthLimit,
2259 [&](const TKey& a, const TKey& b) { return !comparer(a, b); });
2260 }
2261}
2262
2269template <typename TKey, typename TValue>
2270void Sort(Span<TKey>& keys, Span<TValue>& values)
2271{
2272 if (keys.get_Length() != values.get_Length())
2273 {
2274 throw ArgumentException(u"Keys and items must have the same length.");
2275 }
2276 if (keys.get_Length() > 1)
2277 {
2278 int32_t depthLimit = 2 * (static_cast<int32_t>(std::log2(keys.get_Length())) + 1);
2279 Details::IntroSort<TKey, TValue>(keys, values, depthLimit, [&](const TKey& a, const TKey& b) { return a > b; });
2280 }
2281}
2282
2288template <typename T>
2289bool StartsWith(const ReadOnlySpan<T>& span, const T& value)
2290{
2291 if (span.get_Length() == 0)
2292 {
2293 return false; // Empty span cannot start with a value
2294 }
2295 return System::ObjectExt::Equals<T>(span.get(0), value);
2296}
2297
2302inline bool StartsWith(const ReadOnlySpan<String>& span, const char16_t* val)
2303{
2304 if (span.get_Length() == 0)
2305 {
2306 return false;
2307 }
2308 String value = String(val);
2309 return (span.get(0)).Equals(value);
2310}
2311
2317template <typename T>
2318bool StartsWith(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& value)
2319{
2320 if (value.get_Length() > span.get_Length())
2321 {
2322 return false;
2323 }
2324
2325 for (int32_t i = 0; i < value.get_Length(); ++i)
2326 {
2327 if (!System::ObjectExt::Equals(span.get(i), value.get(i)))
2328 {
2329 return false;
2330 }
2331 }
2332
2333 return true;
2334}
2335
2341template <typename T>
2342bool StartsWith(const Span<T>& span, const ReadOnlySpan<T>& value)
2343{
2344 return StartsWith(static_cast<ReadOnlySpan<T>>(span), value);
2345}
2346
2352template <typename T>
2353bool StartsWith(const ReadOnlySpan<T>& span, const Span<T>& value)
2354{
2355 return StartsWith(span, static_cast<ReadOnlySpan<T>>(value));
2356}
2357
2363ASPOSECPP_SHARED_API bool StartsWith(const ReadOnlySpan<char16_t>& span, const ReadOnlySpan<char16_t>& value,
2364 StringComparison comparisonType);
2365
2371ASPOSECPP_SHARED_API int32_t ToLower(const ReadOnlySpan<char16_t>& source, Span<char16_t>& destination,
2373
2378ASPOSECPP_SHARED_API int32_t ToLowerInvariant(const ReadOnlySpan<char16_t>& source, Span<char16_t>& destination);
2379
2385ASPOSECPP_SHARED_API int32_t ToUpper(const ReadOnlySpan<char16_t>& source, Span<char16_t>& destination,
2387
2392ASPOSECPP_SHARED_API int32_t ToUpperInvariant(const ReadOnlySpan<char16_t>& source, Span<char16_t>& destination);
2393
2399template <typename T>
2400ReadOnlySpan<T> Trim(const ReadOnlySpan<T>& span, T trimElement)
2401{
2402 return Trim(span, ReadOnlySpan<T>(&trimElement, 1));
2403}
2404
2410template <typename T>
2411Span<T> Trim(Span<T>& span, T trimElement)
2412{
2413 return Trim(span, ReadOnlySpan<T>(&trimElement, 1));
2414}
2415
2421template <typename T>
2422ReadOnlySpan<T> Trim(const ReadOnlySpan<T>& span, const ReadOnlySpan<T>& trimElements)
2423{
2424 if (span.get_IsEmpty())
2425 {
2426 return span;
2427 }
2428
2429 int32_t start = 0;
2430 int32_t end = span.get_Length() - 1;
2431
2432 // Trim from the start
2433 while (start <= end && Contains(trimElements, span.get(start)))
2434 {
2435 start++;
2436 }
2437
2438 // Trim from the end
2439 while (end >= start && Contains(trimElements, span.get(end)))
2440 {
2441 end--;
2442 }
2443
2444 return span.Slice(start, end - start + 1);
2445}
2446
2452template <typename T>
2453Span<T> Trim(Span<T>& span, const ReadOnlySpan<T>& trimElements)
2454{
2455 if (span.get_IsEmpty())
2456 {
2457 return span;
2458 }
2459
2460 int32_t start = 0;
2461 int32_t end = span.get_Length() - 1;
2462
2463 // Trim from the start
2464 while (start <= end && Contains(trimElements, span.get(start)))
2465 {
2466 start++;
2467 }
2468
2469 // Trim from the end
2470 while (end >= start && Contains(trimElements, span.get(end)))
2471 {
2472 end--;
2473 }
2474
2475 return span.Slice(start, end - start + 1);
2476}
2477
2482{
2484}
2485
2490{
2492}
2493
2499template <typename T>
2500ReadOnlySpan<T> TrimEnd(const ReadOnlySpan<T>& span, const T& trimElement)
2501{
2502 int32_t endIndex = span.get_Length() - 1;
2503 while (endIndex >= 0 && System::ObjectExt::Equals(span.get(endIndex), trimElement))
2504 {
2505 --endIndex;
2506 }
2507 return span.Slice(0, endIndex + 1);
2508}
2509
2515template <typename T>
2516Span<T> TrimEnd(Span<T>& span, const T& trimElement)
2517{
2518 int32_t endIndex = span.get_Length() - 1;
2519 while (endIndex >= 0 && System::ObjectExt::Equals(span.get(endIndex), trimElement)) // equals
2520 {
2521 --endIndex;
2522 }
2523 return span.Slice(0, endIndex + 1);
2524}
2525
2531template <typename T>
2533{
2534 int32_t endIndex = span.get_Length() - 1;
2535 while (endIndex >= 0 && Contains(trimElements, span.get(endIndex)))
2536 {
2537 --endIndex;
2538 }
2539 return span.Slice(0, endIndex + 1);
2540}
2541
2547template <typename T>
2548Span<T> TrimEnd(Span<T>& span, const ReadOnlySpan<T>& trimElements)
2549{
2550 int32_t endIndex = span.get_Length() - 1;
2551 while (endIndex >= 0 && Contains(trimElements, span.get(endIndex)))
2552 {
2553 --endIndex;
2554 }
2555 return span.Slice(0, endIndex + 1);
2556}
2557
2562{
2564}
2565
2570{
2571 return TrimEnd<char16_t>(span, Details::DefaultWhitespaceSpan);
2572}
2573
2578inline ReadOnlySpan<char16_t> TrimEnd(const ReadOnlySpan<char16_t>& span, char16_t trimchar)
2579{
2580 int32_t endIndex = span.get_Length() - 1;
2581 while (endIndex >= 0 && span.get(endIndex) == trimchar)
2582 {
2583 --endIndex;
2584 }
2585 return span.Slice(0, endIndex + 1);
2586}
2587
2592inline Span<char16_t> TrimEnd(Span<char16_t>& span, char16_t trimchar)
2593{
2594 int32_t endIndex = span.get_Length() - 1;
2595 while (endIndex >= 0 && span.get(endIndex) == trimchar)
2596 {
2597 --endIndex;
2598 }
2599 return span.Slice(0, endIndex + 1);
2600}
2601
2607{
2608 int32_t endIndex = span.get_Length() - 1;
2609 while (endIndex >= 0 && Contains(trimChars, span.get(endIndex)))
2610 {
2611 --endIndex;
2612 }
2613 return span.Slice(0, endIndex + 1);
2614}
2615
2621{
2622 int32_t endIndex = span.get_Length() - 1;
2623 while (endIndex >= 0 && Contains(trimchars, span.get(endIndex)))
2624 {
2625 --endIndex;
2626 }
2627 return span.Slice(0, endIndex + 1);
2628}
2629
2635template <typename T>
2636ReadOnlySpan<T> TrimStart(const ReadOnlySpan<T>& span, const T& trimElement)
2637{
2638 int32_t startIndex = 0;
2639 while (startIndex < span.get_Length() && System::ObjectExt::Equals(span.get(startIndex), trimElement))
2640 {
2641 ++startIndex;
2642 }
2643 return span.Slice(startIndex);
2644}
2645
2651template <typename T>
2652Span<T> TrimStart(Span<T>& span, const T& trimElement)
2653{
2654 int32_t startIndex = 0;
2655 while (startIndex < span.get_Length() && System::ObjectExt::Equals(span.get(startIndex), trimElement))
2656 {
2657 ++startIndex;
2658 }
2659 return span.Slice(startIndex);
2660}
2661
2667template <typename T>
2669{
2670 int32_t startIndex = 0;
2671 while (startIndex < span.get_Length() && Contains(trimElements, span.get(startIndex)))
2672 {
2673 ++startIndex;
2674 }
2675 return span.Slice(startIndex);
2676}
2677
2683template <typename T>
2684Span<T> TrimStart(Span<T>& span, const ReadOnlySpan<T>& trimElements)
2685{
2686 int32_t startIndex = 0;
2687 while (startIndex < span.get_Length() && Contains(trimElements, span.get(startIndex)))
2688 {
2689 ++startIndex;
2690 }
2691 return span.Slice(startIndex);
2692}
2693
2698{
2700}
2701
2706{
2708}
2709
2714inline ReadOnlySpan<char16_t> TrimStart(const ReadOnlySpan<char16_t>& span, char16_t trimchar)
2715{
2716 int32_t startIndex = 0;
2717 while (startIndex < span.get_Length() && span.get(startIndex) == trimchar)
2718 {
2719 ++startIndex;
2720 }
2721 return span.Slice(startIndex);
2722}
2723
2728inline Span<char16_t> TrimStart(Span<char16_t>& span, char16_t trimchar)
2729{
2730 int32_t startIndex = 0;
2731 while (startIndex < span.get_Length() && span.get(startIndex) == trimchar)
2732 {
2733 ++startIndex;
2734 }
2735 return span.Slice(startIndex);
2736}
2737
2743{
2744 int32_t startIndex = 0;
2745 while (startIndex < span.get_Length() && Contains(trimchars, span.get(startIndex)))
2746 {
2747 ++startIndex;
2748 }
2749 return span.Slice(startIndex);
2750}
2751
2757{
2758 int32_t startIndex = 0;
2759 while (startIndex < span.get_Length() && Contains(trimchars, span.get(startIndex)))
2760 {
2761 ++startIndex;
2762 }
2763 return span.Slice(startIndex);
2764}
2765
2766} // namespace MemoryExtensions
2767} // namespace System
2768#endif // _aspose_system_memory_extensions_
2769
Represents a pointer to the method that compares two objects of the same type. This type should be al...
Definition: comparison.h:93
static std::enable_if< IsExceptionWrapper< T >::value, bool >::type Equals(const T &obj, const T2 &another)
Definition: object_ext.h:34
Forward to use within Span class.
Definition: span.h:396
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:357
String class used across the library. Is a substitute for C# System.String when translating code....
Definition: string.h:122
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:130
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:230
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:333
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:274
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:247
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:83
int32_t Compare(const SharedPtr< T > &a, const SharedPtr< U > &b)
Compares two smart pointers.
Definition: memory_extensions.h:33
int32_t BinarySearchImpl(const ReadOnlySpan< T > &span, const TValue &value, TCompareFunc compareFunc)
Common binary search implementation.
Definition: memory_extensions.h:388
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:300
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:174
int32_t BinarySearch(const ReadOnlySpan< T > &span, const TComparable &comparable)
Performs binary search on a sorted span.
Definition: memory_extensions.h:456
int32_t SequenceCompareTo(const ReadOnlySpan< T > &span, const ReadOnlySpan< T > &other)
Compares two ReadOnlySpans lexicographically.
Definition: memory_extensions.h:2066
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:1237
bool Overlaps(const ReadOnlySpan< T > &span, const ReadOnlySpan< T > &other)
Determines if two ReadOnlySpans overlap in memory without calculating offset.
Definition: memory_extensions.h:1942
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:1881
ReadOnlySpan< T > TrimEnd(const ReadOnlySpan< T > &span, const T &trimElement)
Trims specified element from the end of a typed span.
Definition: memory_extensions.h:2500
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:1912
int32_t ToUpperInvariant(const ReadOnlySpan< char16_t > &source, Span< char16_t > &destination)
Converts characters to uppercase using invariant culture.
int32_t IndexOf(const ReadOnlySpan< char16_t > &span, const ReadOnlySpan< char16_t > &value, StringComparison comparisonType)
Finds the index of a ReadOnlySpan<char16_t> value in a ReadOnlySpan<char16_t> with StringComparison.
void Reverse(Span< T > &span)
Reverses the order of elements in a Span in-place.
Definition: memory_extensions.h:2048
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:917
void CopyTo(const ArrayPtr< T > &source, Span< T > &destination)
Copies elements from an array to a span.
Definition: memory_extensions.h:953
bool StartsWith(const ReadOnlySpan< T > &span, const T &value)
Checks if the span starts with the specified value.
Definition: memory_extensions.h:2289
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:2005
bool Contains(const ReadOnlySpan< char16_t > &span, const ReadOnlySpan< char16_t > &value, StringComparison comparisonType)
Checks if a character span contains another character span with specified comparison rules.
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:879
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:1735
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:1333
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:511
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:2129
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:1627
ReadOnlySpan< char16_t > AsSpan(const String &text, int32_t start=0, int32_t length=-1)
Creates a read-only span from a string.
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:1468
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:661
ReadOnlySpan< T > Trim(const ReadOnlySpan< T > &span, T trimElement)
Trims specified element from both ends of a typed span.
Definition: memory_extensions.h:2400
void Sort(const Span< T > &span, const SharedPtr< TComparer > &comparer)
Sorts a Span using a custom comparer.
Definition: memory_extensions.h:2204
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:741
int32_t LastIndexOf(const ReadOnlySpan< char16_t > &span, const ReadOnlySpan< char16_t > &value, StringComparison comparisonType)
Finds the last occurrence of a value within a span using specified string comparison.
int32_t Count(const ReadOnlySpan< T > &span, const T &value)
Counts occurrences of a value in a read-only span.
Definition: memory_extensions.h:964
int32_t ToUpper(const ReadOnlySpan< char16_t > &source, Span< char16_t > &destination, const SharedPtr< Globalization::CultureInfo > &culture)
Converts characters to uppercase using specified culture.
ReadOnlySpan< T > TrimStart(const ReadOnlySpan< T > &span, const T &trimElement)
Trims specified element from the start of a typed span.
Definition: memory_extensions.h:2636
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:1499
bool IsWhiteSpace(const ReadOnlySpan< char16_t > &span)
Checks if the entire span consists only of whitespace characters.
bool EndsWith(const ReadOnlySpan< char16_t > &span, const ReadOnlySpan< char16_t > &value, StringComparison comparisonType)
Determines if a ReadOnlySpan<char16_t> ends with the specified value using StringComparison.
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