A game about forced loneliness, made by TACStudios
1
2//------------------------------------------------------------------------------
3// <auto-generated>
4// This code was generated by a tool.
5//
6// TextTransform Packages/com.unity.collections/Unity.Collections/NativeText.tt
7//
8// Changes to this file may cause incorrect behavior and will be lost if
9// the code is regenerated.
10// </auto-generated>
11//------------------------------------------------------------------------------
12
13using System;
14using System.Collections;
15using System.Collections.Generic;
16using System.Diagnostics;
17using System.Runtime.InteropServices;
18using System.Runtime.CompilerServices;
19using Unity.Burst;
20using Unity.Collections.LowLevel.Unsafe;
21using Unity.Jobs;
22using UnityEngine.Internal;
23using Unity.Properties;
24
25
26
27namespace Unity.Collections
28{
29 /// <summary>
30 /// An unmanaged, mutable, resizable UTF-8 string.
31 /// </summary>
32 /// <remarks>
33 /// The string is always null-terminated, meaning a zero byte always immediately follows the last character.
34 /// </remarks>
35 [StructLayout(LayoutKind.Sequential)]
36 [NativeContainer]
37 [DebuggerDisplay("Length = {Length}")]
38 [GenerateTestsForBurstCompatibility]
39 public unsafe partial struct NativeText
40 : INativeList<byte>
41 , INativeDisposable
42 , IUTF8Bytes
43 , IComparable<String>
44 , IEquatable<String>
45 , IComparable<NativeText>
46 , IEquatable<NativeText>
47 , IComparable<FixedString32Bytes>
48 , IEquatable<FixedString32Bytes>
49 , IComparable<FixedString64Bytes>
50 , IEquatable<FixedString64Bytes>
51 , IComparable<FixedString128Bytes>
52 , IEquatable<FixedString128Bytes>
53 , IComparable<FixedString512Bytes>
54 , IEquatable<FixedString512Bytes>
55 , IComparable<FixedString4096Bytes>
56 , IEquatable<FixedString4096Bytes>
57 {
58#if ENABLE_UNITY_COLLECTIONS_CHECKS
59 internal AtomicSafetyHandle m_Safety;
60 internal static readonly SharedStatic<int> s_staticSafetyId = SharedStatic<int>.GetOrCreate<NativeText>();
61#endif
62 // NOTE! This Length is always > 0, because we have a null terminating byte.
63 // We hide this byte from NativeText users.
64 [NativeDisableUnsafePtrRestriction]
65 internal UnsafeText* m_Data;
66
67 /// <summary>
68 /// Initializes and returns an instance of NativeText with the characters copied from another string.
69 /// </summary>
70 /// <param name="source">A string to copy characters from.</param>
71 /// <param name="allocator">The allocator to use.</param>
72 [ExcludeFromBurstCompatTesting("Takes managed string")]
73 public NativeText(String source, Allocator allocator) : this(source, (AllocatorManager.AllocatorHandle)allocator)
74 {
75 }
76
77 /// <summary>
78 /// Initializes and returns an instance of NativeText with the characters copied from another string.
79 /// </summary>
80 /// <param name="source">A string to copy characters from.</param>
81 /// <param name="allocator">The allocator to use.</param>
82 [ExcludeFromBurstCompatTesting("Takes managed string")]
83 public NativeText(String source, AllocatorManager.AllocatorHandle allocator) : this(source.Length * 2, allocator)
84 {
85 Length = source.Length * 2;
86 unsafe
87 {
88 fixed (char* sourceptr = source)
89 {
90 var error = UTF8ArrayUnsafeUtility.Copy(GetUnsafePtr(), out var actualBytes, Capacity, sourceptr, source.Length);
91 if (error != CopyError.None)
92 {
93 CheckNull(m_Data);
94 m_Data->Dispose();
95 m_Data = UnsafeText.Alloc(allocator);
96 *m_Data = default(UnsafeText);
97 ThrowCopyError(error, source);
98 }
99 Length = actualBytes;
100 }
101 }
102
103#if ENABLE_UNITY_COLLECTIONS_CHECKS
104 CollectionHelper.SetStaticSafetyId(ref m_Safety, ref s_staticSafetyId.Data, "Unity.Collections.NativeText");
105
106 AtomicSafetyHandle.SetBumpSecondaryVersionOnScheduleWrite(m_Safety, true);
107#endif
108 }
109
110 /// <summary>
111 /// Initializes and returns an instance of NativeText.
112 /// </summary>
113 /// <param name="capacity">The initial capacity in bytes.</param>
114 /// <param name="allocator">The allocator to use.</param>
115 public NativeText(int capacity, Allocator allocator) : this(capacity, (AllocatorManager.AllocatorHandle)allocator)
116 {
117 }
118
119 /// <summary>
120 /// Initializes and returns an instance of NativeText.
121 /// </summary>
122 /// <param name="capacity">The initial capacity in bytes.</param>
123 /// <param name="allocator">The allocator to use.</param>
124 public NativeText(int capacity, AllocatorManager.AllocatorHandle allocator)
125 {
126#if ENABLE_UNITY_COLLECTIONS_CHECKS
127 CollectionHelper.CheckAllocator(allocator);
128
129 m_Safety = CollectionHelper.CreateSafetyHandle(allocator);
130
131 CollectionHelper.SetStaticSafetyId(ref m_Safety, ref s_staticSafetyId.Data, "Unity.Collections.NativeText");
132
133 AtomicSafetyHandle.SetBumpSecondaryVersionOnScheduleWrite(m_Safety, true);
134#endif
135 m_Data = UnsafeText.Alloc(allocator);
136 *m_Data = new UnsafeText(capacity, allocator);
137 }
138
139 /// <summary>
140 /// Initializes and returns an instance of NativeText with an initial capacity of 512 bytes.
141 /// </summary>
142 /// <param name="allocator">The allocator to use.</param>
143 public NativeText(Allocator allocator) : this((AllocatorManager.AllocatorHandle)allocator)
144 {
145 }
146
147 /// <summary>
148 /// Initializes and returns an instance of NativeText with an initial capacity of 512 bytes.
149 /// </summary>
150 /// <param name="allocator">The allocator to use.</param>
151 public NativeText(AllocatorManager.AllocatorHandle allocator) : this(512, allocator)
152 {
153 }
154
155 /// <summary>
156 /// Initializes and returns an instance of NativeText with the characters copied from another string.
157 /// </summary>
158 /// <param name="source">A string to copy characters from.</param>
159 /// <param name="allocator">The allocator to use.</param>
160 public NativeText(in FixedString32Bytes source, AllocatorManager.AllocatorHandle allocator)
161 : this(source.utf8LengthInBytes, allocator)
162 {
163 Length = source.utf8LengthInBytes;
164 unsafe {
165 byte* sbytes = (byte*) UnsafeUtilityExtensions.AddressOf(source.bytes);
166 byte* dbytes = (byte*) m_Data->GetUnsafePtr();
167 UnsafeUtility.MemCpy(dbytes, sbytes, source.utf8LengthInBytes);
168 }
169 }
170
171 /// <summary>
172 /// Initializes and returns an instance of NativeText with the characters copied from another string.
173 /// </summary>
174 /// <param name="source">A string to copy characters from.</param>
175 /// <param name="allocator">The allocator to use.</param>
176 public NativeText(in FixedString32Bytes source, Allocator allocator)
177 : this(source, (AllocatorManager.AllocatorHandle)allocator)
178 {
179 }
180
181 /// <summary>
182 /// Initializes and returns an instance of NativeText with the characters copied from another string.
183 /// </summary>
184 /// <param name="source">A string to copy characters from.</param>
185 /// <param name="allocator">The allocator to use.</param>
186 public NativeText(in FixedString64Bytes source, AllocatorManager.AllocatorHandle allocator)
187 : this(source.utf8LengthInBytes, allocator)
188 {
189 Length = source.utf8LengthInBytes;
190 unsafe {
191 byte* sbytes = (byte*) UnsafeUtilityExtensions.AddressOf(source.bytes);
192 byte* dbytes = (byte*) m_Data->GetUnsafePtr();
193 UnsafeUtility.MemCpy(dbytes, sbytes, source.utf8LengthInBytes);
194 }
195 }
196
197 /// <summary>
198 /// Initializes and returns an instance of NativeText with the characters copied from another string.
199 /// </summary>
200 /// <param name="source">A string to copy characters from.</param>
201 /// <param name="allocator">The allocator to use.</param>
202 public NativeText(in FixedString64Bytes source, Allocator allocator)
203 : this(source, (AllocatorManager.AllocatorHandle)allocator)
204 {
205 }
206
207 /// <summary>
208 /// Initializes and returns an instance of NativeText with the characters copied from another string.
209 /// </summary>
210 /// <param name="source">A string to copy characters from.</param>
211 /// <param name="allocator">The allocator to use.</param>
212 public NativeText(in FixedString128Bytes source, AllocatorManager.AllocatorHandle allocator)
213 : this(source.utf8LengthInBytes, allocator)
214 {
215 Length = source.utf8LengthInBytes;
216 unsafe {
217 byte* sbytes = (byte*) UnsafeUtilityExtensions.AddressOf(source.bytes);
218 byte* dbytes = (byte*) m_Data->GetUnsafePtr();
219 UnsafeUtility.MemCpy(dbytes, sbytes, source.utf8LengthInBytes);
220 }
221 }
222
223 /// <summary>
224 /// Initializes and returns an instance of NativeText with the characters copied from another string.
225 /// </summary>
226 /// <param name="source">A string to copy characters from.</param>
227 /// <param name="allocator">The allocator to use.</param>
228 public NativeText(in FixedString128Bytes source, Allocator allocator)
229 : this(source, (AllocatorManager.AllocatorHandle)allocator)
230 {
231 }
232
233 /// <summary>
234 /// Initializes and returns an instance of NativeText with the characters copied from another string.
235 /// </summary>
236 /// <param name="source">A string to copy characters from.</param>
237 /// <param name="allocator">The allocator to use.</param>
238 public NativeText(in FixedString512Bytes source, AllocatorManager.AllocatorHandle allocator)
239 : this(source.utf8LengthInBytes, allocator)
240 {
241 Length = source.utf8LengthInBytes;
242 unsafe {
243 byte* sbytes = (byte*) UnsafeUtilityExtensions.AddressOf(source.bytes);
244 byte* dbytes = (byte*) m_Data->GetUnsafePtr();
245 UnsafeUtility.MemCpy(dbytes, sbytes, source.utf8LengthInBytes);
246 }
247 }
248
249 /// <summary>
250 /// Initializes and returns an instance of NativeText with the characters copied from another string.
251 /// </summary>
252 /// <param name="source">A string to copy characters from.</param>
253 /// <param name="allocator">The allocator to use.</param>
254 public NativeText(in FixedString512Bytes source, Allocator allocator)
255 : this(source, (AllocatorManager.AllocatorHandle)allocator)
256 {
257 }
258
259 /// <summary>
260 /// Initializes and returns an instance of NativeText with the characters copied from another string.
261 /// </summary>
262 /// <param name="source">A string to copy characters from.</param>
263 /// <param name="allocator">The allocator to use.</param>
264 public NativeText(in FixedString4096Bytes source, AllocatorManager.AllocatorHandle allocator)
265 : this(source.utf8LengthInBytes, allocator)
266 {
267 Length = source.utf8LengthInBytes;
268 unsafe {
269 byte* sbytes = (byte*) UnsafeUtilityExtensions.AddressOf(source.bytes);
270 byte* dbytes = (byte*) m_Data->GetUnsafePtr();
271 UnsafeUtility.MemCpy(dbytes, sbytes, source.utf8LengthInBytes);
272 }
273 }
274
275 /// <summary>
276 /// Initializes and returns an instance of NativeText with the characters copied from another string.
277 /// </summary>
278 /// <param name="source">A string to copy characters from.</param>
279 /// <param name="allocator">The allocator to use.</param>
280 public NativeText(in FixedString4096Bytes source, Allocator allocator)
281 : this(source, (AllocatorManager.AllocatorHandle)allocator)
282 {
283 }
284
285
286 /// <summary>
287 /// The current length in bytes of this string.
288 /// </summary>
289 /// <remarks>
290 /// The length does not include the null terminator byte.
291 /// </remarks>
292 /// <value>The current length in bytes of the UTF-8 encoded string.</value>
293 public int Length
294 {
295 [MethodImpl(MethodImplOptions.AggressiveInlining)]
296 readonly get
297 {
298 CheckNull(m_Data);
299 CheckRead();
300 return m_Data->Length;
301 }
302
303 set
304 {
305 CheckNull(m_Data);
306 CheckWriteAndBumpSecondaryVersion();
307 m_Data->Length = value;
308 }
309 }
310
311 /// <summary>
312 /// The current capacity in bytes of this string.
313 /// </summary>
314 /// <remarks>
315 /// The null-terminator byte is not included in the capacity, so the string's character buffer is `Capacity + 1` in size.
316 /// </remarks>
317 /// <value>The current capacity in bytes of the string.</value>
318 public int Capacity
319 {
320 [MethodImpl(MethodImplOptions.AggressiveInlining)]
321 readonly get
322 {
323 CheckNull(m_Data);
324 CheckRead();
325 return m_Data->Capacity;
326 }
327
328 set
329 {
330 CheckNull(m_Data);
331 CheckWriteAndBumpSecondaryVersion();
332 m_Data->Capacity = value;
333 }
334 }
335
336 /// <summary>
337 /// Attempt to set the length in bytes of this string.
338 /// </summary>
339 /// <param name="newLength">The new length in bytes of the string.</param>
340 /// <param name="clearOptions">Whether any bytes added should be zeroed out.</param>
341 /// <returns>Always true.</returns>
342 public bool TryResize(int newLength, NativeArrayOptions clearOptions = NativeArrayOptions.ClearMemory)
343 {
344 CheckWrite();
345
346 // this can't ever fail, because if we can't resize malloc will abort
347 Length = newLength;
348 return true;
349 }
350
351 /// <summary>
352 /// Whether this string has no characters.
353 /// </summary>
354 /// <value>True if this string has no characters or the string has not been constructed.</value>
355 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined and a write is attempted.</exception>
356 public readonly bool IsEmpty
357 {
358 [MethodImpl(MethodImplOptions.AggressiveInlining)]
359 get
360 {
361 if (!IsCreated)
362 {
363 return true;
364 }
365
366 CheckRead();
367 return m_Data->IsEmpty;
368 }
369 }
370
371 /// <summary>
372 /// Whether this string's character buffer has been allocated (and not yet deallocated).
373 /// </summary>
374 /// <value>Whether this string's character buffer has been allocated (and not yet deallocated).</value>
375 public readonly bool IsCreated
376 {
377 [MethodImpl(MethodImplOptions.AggressiveInlining)]
378 get => m_Data != null;
379 }
380
381 /// <summary>
382 /// Returns a pointer to this string's character buffer.
383 /// </summary>
384 /// <remarks>
385 /// The pointer is made invalid by operations that reallocate the character buffer, such as setting <see cref="Capacity"/>.
386 /// </remarks>
387 /// <returns>A pointer to this string's character buffer.</returns>
388 public unsafe byte* GetUnsafePtr()
389 {
390 CheckNull(m_Data);
391 CheckRead();
392 return m_Data->GetUnsafePtr();
393 }
394
395 /// <summary>
396 /// The byte at an index. Note that writing to a NativeText.Readonly is not supported; the setter of this property throws when safety checks are enabled.
397 /// </summary>
398 /// <param name="index">A zero-based byte index.</param>
399 /// <value>The byte at the index.</value>
400 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception>
401 public byte this[int index]
402 {
403 [MethodImpl(MethodImplOptions.AggressiveInlining)]
404 get
405 {
406 CheckNull(m_Data);
407 CheckRead();
408 return m_Data->ElementAt(index);
409 }
410 [MethodImpl(MethodImplOptions.AggressiveInlining)]
411 set
412 {
413 CheckNull(m_Data);
414 CheckWrite();
415 m_Data->ElementAt(index) = value;
416 }
417 }
418
419 /// <summary>
420 /// Returns a reference to the byte (not character) at an index.
421 /// </summary>
422 /// <remarks>
423 /// Deallocating or reallocating this string's character buffer makes the reference invalid.
424 /// </remarks>
425 /// <param name="index">A byte index.</param>
426 /// <returns>A reference to the byte at the index.</returns>
427 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception>
428 [MethodImpl(MethodImplOptions.AggressiveInlining)]
429 public ref byte ElementAt(int index)
430 {
431 CheckNull(m_Data);
432 CheckWrite();
433 return ref m_Data->ElementAt(index);
434 }
435
436 /// <summary>
437 /// Sets the length to 0.
438 /// </summary>
439 public void Clear()
440 {
441 Length = 0;
442 }
443
444 /// <summary>
445 /// Appends a byte.
446 /// </summary>
447 /// <remarks>
448 /// A zero byte will always follow the newly appended byte.
449 ///
450 /// No validation is performed: it is your responsibility for the bytes of the string to form valid UTF-8 when you're done appending bytes.
451 /// </remarks>
452 /// <param name="value">A byte to append.</param>
453 [MethodImpl(MethodImplOptions.AggressiveInlining)]
454 public void Add(in byte value)
455 {
456 CheckWrite();
457 this[Length++] = value;
458 }
459
460 /// <summary>
461 /// Returns the lexicographical sort order of this string relative to another.
462 /// </summary>
463 /// <param name="other">Another string to compare with.</param>
464 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
465 ///
466 /// 0 denotes both strings have the same sort position.<br/>
467 /// -1 denotes that this string should be sorted to precede the other.<br/>
468 /// +1 denotes that this string should be sorted to follow the other.<br/>
469 /// </returns>
470 public int CompareTo(NativeText other)
471 {
472 CheckRead();
473 return FixedStringMethods.CompareTo(ref this, *other.m_Data);
474 }
475
476 /// <summary>
477 /// Returns true if this string and another are equal.
478 /// </summary>
479 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
480 /// <param name="other">Another string to compare with.</param>
481 /// <returns>True if the two strings are equal.</returns>
482 public bool Equals(NativeText other)
483 {
484 CheckRead();
485 return FixedStringMethods.Equals(ref this, *other.m_Data);
486 }
487
488 /// <summary>
489 /// Returns the lexicographical sort order of this string relative to another.
490 /// </summary>
491 /// <param name="other">Another string to compare with.</param>
492 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
493 ///
494 /// 0 denotes both strings have the same sort position.<br/>
495 /// -1 denotes that this string should be sorted to precede the other.<br/>
496 /// +1 denotes that this string should be sorted to follow the other.<br/>
497 /// </returns>
498 public int CompareTo(NativeText.ReadOnly other)
499 {
500 CheckRead();
501 return FixedStringMethods.CompareTo(ref this, other);
502 }
503
504 /// <summary>
505 /// Returns true if this string and another are equal.
506 /// </summary>
507 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
508 /// <param name="other">Another string to compare with.</param>
509 /// <returns>True if the two strings are equal.</returns>
510 public bool Equals(NativeText.ReadOnly other)
511 {
512 CheckRead();
513 return FixedStringMethods.Equals(ref this, *other.m_Data);
514 }
515
516 /// <summary>
517 /// Releases all resources (memory and safety handles).
518 /// </summary>
519 public void Dispose()
520 {
521#if ENABLE_UNITY_COLLECTIONS_CHECKS
522 if (!AtomicSafetyHandle.IsDefaultValue(m_Safety))
523 {
524 AtomicSafetyHandle.CheckExistsAndThrow(m_Safety);
525 }
526#endif
527 if (!IsCreated)
528 {
529 return;
530 }
531
532#if ENABLE_UNITY_COLLECTIONS_CHECKS
533 CollectionHelper.DisposeSafetyHandle(ref m_Safety);
534#endif
535 UnsafeText.Free(m_Data);
536 m_Data = null;
537 }
538
539 /// <summary>
540 /// Creates and schedules a job that releases all resources (memory and safety handles) of this NativeText.
541 /// </summary>
542 /// <param name="inputDeps">The dependency for the new job.</param>
543 /// <returns>The handle of the new job. The job depends upon `inputDeps` and releases all resources (memory and safety handles) of this NativeText.</returns>
544 public JobHandle Dispose(JobHandle inputDeps)
545 {
546#if ENABLE_UNITY_COLLECTIONS_CHECKS
547 if (!AtomicSafetyHandle.IsDefaultValue(m_Safety))
548 {
549 AtomicSafetyHandle.CheckExistsAndThrow(m_Safety);
550 }
551#endif
552 if (!IsCreated)
553 {
554 return inputDeps;
555 }
556
557#if ENABLE_UNITY_COLLECTIONS_CHECKS
558 var jobHandle = new NativeTextDisposeJob { Data = new NativeTextDispose { m_TextData = m_Data, m_Safety = m_Safety } }.Schedule(inputDeps);
559 AtomicSafetyHandle.Release(m_Safety);
560#else
561 var jobHandle = new NativeTextDisposeJob { Data = new NativeTextDispose { m_TextData = m_Data } }.Schedule(inputDeps);
562#endif
563 m_Data = null;
564
565 return jobHandle;
566 }
567
568 /// <summary>
569 /// A copy of this string as a managed string.
570 /// </summary>
571 /// <remarks>
572 /// For internal use only. Use <see cref="ToString"/> instead.
573 /// </remarks>
574 /// <value>A copy of this string as a managed string.</value>
575 [CreateProperty]
576 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
577 [ExcludeFromBurstCompatTesting("Returns managed string")]
578 public string Value => ToString();
579
580 /// <summary>
581 /// An enumerator over the characters (not bytes) of a NativeText.
582 /// </summary>
583 /// <remarks>
584 /// In an enumerator's initial state, its index is invalid. The first <see cref="MoveNext"/> call advances the enumerator's index to the first character.
585 /// </remarks>
586 public struct Enumerator : IEnumerator<Unicode.Rune>
587 {
588 NativeText.ReadOnly target;
589 int offset;
590 Unicode.Rune current;
591
592 /// <summary>
593 /// Initializes and returns an instance of NativeText.Enumerator.
594 /// </summary>
595 /// <param name="source">A NativeText for which to create an enumerator.</param>
596 public Enumerator(NativeText source)
597 {
598#if ENABLE_UNITY_COLLECTIONS_CHECKS
599 AtomicSafetyHandle.CheckGetSecondaryDataPointerAndThrow(source.m_Safety);
600
601 var ash = source.m_Safety;
602 AtomicSafetyHandle.UseSecondaryVersion(ref ash);
603
604 target = new ReadOnly(source.m_Data, ash);
605#else
606 target = source.AsReadOnly();
607#endif
608 offset = 0;
609 current = default;
610 }
611
612
613 /// <summary>
614 /// Initializes and returns an instance of NativeText.Enumerator.
615 /// </summary>
616 /// <param name="source">A NativeText.ReadOnly for which to create an enumerator.</param>
617 public Enumerator(NativeText.ReadOnly source)
618 {
619#if ENABLE_UNITY_COLLECTIONS_CHECKS
620 AtomicSafetyHandle.CheckGetSecondaryDataPointerAndThrow(source.m_Safety);
621
622 var ash = source.m_Safety;
623 AtomicSafetyHandle.UseSecondaryVersion(ref ash);
624
625 target = new ReadOnly(source.m_Data, ash);
626#else
627 target = source;
628#endif
629 offset = 0;
630 current = default;
631 }
632
633 /// <summary>
634 /// Does nothing.
635 /// </summary>
636 public void Dispose()
637 {
638 }
639
640 /// <summary>
641 /// Advances the enumerator to the next character, returning true if <see cref="Current"/> is valid to read afterwards.
642 /// </summary>
643 /// <returns>True if <see cref="Current"/> is valid to read after the call.</returns>
644 [MethodImpl(MethodImplOptions.AggressiveInlining)]
645 public bool MoveNext()
646 {
647 if (offset >= target.Length)
648 return false;
649
650 unsafe
651 {
652 Unicode.Utf8ToUcs(out current, target.GetUnsafePtr(), ref offset, target.Length);
653 }
654
655 return true;
656 }
657
658 /// <summary>
659 /// Resets the enumerator to its initial state.
660 /// </summary>
661 public void Reset()
662 {
663 offset = 0;
664 current = default;
665 }
666
667 object IEnumerator.Current
668 {
669 [MethodImpl(MethodImplOptions.AggressiveInlining)]
670 get => Current;
671 }
672
673 /// <summary>
674 /// The current character.
675 /// </summary>
676 /// <value>The current character.</value>
677 public Unicode.Rune Current => current;
678 }
679
680 /// <summary>
681 /// Returns an enumerator for iterating over the characters of the NativeText.
682 /// </summary>
683 /// <returns>An enumerator for iterating over the characters of the NativeText.</returns>
684 public Enumerator GetEnumerator()
685 {
686 return new Enumerator(this);
687 }
688
689 /// <summary>
690 /// Returns the lexicographical sort order of this string relative to another.
691 /// </summary>
692 /// <param name="other">Another string to compare with.</param>
693 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
694 ///
695 /// 0 denotes both strings have the same sort position.<br/>
696 /// -1 denotes that this string should be sorted to precede the other.<br/>
697 /// +1 denotes that this string should be sorted to follow the other.<br/>
698 /// </returns>
699 [ExcludeFromBurstCompatTesting("Takes managed string")]
700 public int CompareTo(String other)
701 {
702 return ToString().CompareTo(other);
703 }
704
705 /// <summary>
706 /// Returns true if this string and another are equal.
707 /// </summary>
708 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
709 /// <param name="other">Another string to compare with.</param>
710 /// <returns>True if the two strings are equal.</returns>
711 [ExcludeFromBurstCompatTesting("Takes managed string")]
712 public bool Equals(String other)
713 {
714 return ToString().Equals(other);
715 }
716
717
718
719 /// <summary>
720 /// Returns the lexicographical sort order of this string relative to another.
721 /// </summary>
722 /// <param name="other">Another string to compare with.</param>
723 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
724 ///
725 /// 0 denotes both strings have the same sort position.<br/>
726 /// -1 denotes that this string should be sorted to precede the other.<br/>
727 /// +1 denotes that this string should be sorted to follow the other.<br/>
728 /// </returns>
729 public int CompareTo(FixedString32Bytes other)
730 {
731 return FixedStringMethods.CompareTo(ref this, other);
732 }
733
734
735 /// <summary>
736 /// Returns true if two strings are equal.
737 /// </summary>
738 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
739 /// <param name="a">A string to compare.</param>
740 /// <param name="b">Another string to compare.</param>
741 /// <returns>True if the two strings are equal.</returns>
742 public static bool operator ==(in NativeText a, in FixedString32Bytes b)
743 {
744 unsafe {
745 var aref = UnsafeUtilityExtensions.AsRef(a);
746 int alen = aref.Length;
747 int blen = b.utf8LengthInBytes;
748 byte* aptr = (byte*) aref.GetUnsafePtr();
749 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes);
750 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen);
751 }
752 }
753
754 /// <summary>
755 /// Returns true if two strings are unequal.
756 /// </summary>
757 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
758 /// <param name="a">A string to compare.</param>
759 /// <param name="b">Another string to compare.</param>
760 /// <returns>True if the two strings are unequal.</returns>
761 public static bool operator !=(in NativeText a, in FixedString32Bytes b)
762 {
763 return !(a == b);
764 }
765
766 /// <summary>
767 /// Returns true if this string and another are equal.
768 /// </summary>
769 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
770 /// <param name="other">Another string to compare with.</param>
771 /// <returns>True if the two strings are equal.</returns>
772 public bool Equals(FixedString32Bytes other)
773 {
774 return this == other;
775 }
776
777 /// <summary>
778 /// Returns the lexicographical sort order of this string relative to another.
779 /// </summary>
780 /// <param name="other">Another string to compare with.</param>
781 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
782 ///
783 /// 0 denotes both strings have the same sort position.<br/>
784 /// -1 denotes that this string should be sorted to precede the other.<br/>
785 /// +1 denotes that this string should be sorted to follow the other.<br/>
786 /// </returns>
787 public int CompareTo(FixedString64Bytes other)
788 {
789 return FixedStringMethods.CompareTo(ref this, other);
790 }
791
792
793 /// <summary>
794 /// Returns true if two strings are equal.
795 /// </summary>
796 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
797 /// <param name="a">A string to compare.</param>
798 /// <param name="b">Another string to compare.</param>
799 /// <returns>True if the two strings are equal.</returns>
800 public static bool operator ==(in NativeText a, in FixedString64Bytes b)
801 {
802 unsafe {
803 var aref = UnsafeUtilityExtensions.AsRef(a);
804 int alen = aref.Length;
805 int blen = b.utf8LengthInBytes;
806 byte* aptr = (byte*) aref.GetUnsafePtr();
807 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes);
808 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen);
809 }
810 }
811
812 /// <summary>
813 /// Returns true if two strings are unequal.
814 /// </summary>
815 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
816 /// <param name="a">A string to compare.</param>
817 /// <param name="b">Another string to compare.</param>
818 /// <returns>True if the two strings are unequal.</returns>
819 public static bool operator !=(in NativeText a, in FixedString64Bytes b)
820 {
821 return !(a == b);
822 }
823
824 /// <summary>
825 /// Returns true if this string and another are equal.
826 /// </summary>
827 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
828 /// <param name="other">Another string to compare with.</param>
829 /// <returns>True if the two strings are equal.</returns>
830 public bool Equals(FixedString64Bytes other)
831 {
832 return this == other;
833 }
834
835 /// <summary>
836 /// Returns the lexicographical sort order of this string relative to another.
837 /// </summary>
838 /// <param name="other">Another string to compare with.</param>
839 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
840 ///
841 /// 0 denotes both strings have the same sort position.<br/>
842 /// -1 denotes that this string should be sorted to precede the other.<br/>
843 /// +1 denotes that this string should be sorted to follow the other.<br/>
844 /// </returns>
845 public int CompareTo(FixedString128Bytes other)
846 {
847 return FixedStringMethods.CompareTo(ref this, other);
848 }
849
850
851 /// <summary>
852 /// Returns true if two strings are equal.
853 /// </summary>
854 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
855 /// <param name="a">A string to compare.</param>
856 /// <param name="b">Another string to compare.</param>
857 /// <returns>True if the two strings are equal.</returns>
858 public static bool operator ==(in NativeText a, in FixedString128Bytes b)
859 {
860 unsafe {
861 var aref = UnsafeUtilityExtensions.AsRef(a);
862 int alen = aref.Length;
863 int blen = b.utf8LengthInBytes;
864 byte* aptr = (byte*) aref.GetUnsafePtr();
865 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes);
866 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen);
867 }
868 }
869
870 /// <summary>
871 /// Returns true if two strings are unequal.
872 /// </summary>
873 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
874 /// <param name="a">A string to compare.</param>
875 /// <param name="b">Another string to compare.</param>
876 /// <returns>True if the two strings are unequal.</returns>
877 public static bool operator !=(in NativeText a, in FixedString128Bytes b)
878 {
879 return !(a == b);
880 }
881
882 /// <summary>
883 /// Returns true if this string and another are equal.
884 /// </summary>
885 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
886 /// <param name="other">Another string to compare with.</param>
887 /// <returns>True if the two strings are equal.</returns>
888 public bool Equals(FixedString128Bytes other)
889 {
890 return this == other;
891 }
892
893 /// <summary>
894 /// Returns the lexicographical sort order of this string relative to another.
895 /// </summary>
896 /// <param name="other">Another string to compare with.</param>
897 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
898 ///
899 /// 0 denotes both strings have the same sort position.<br/>
900 /// -1 denotes that this string should be sorted to precede the other.<br/>
901 /// +1 denotes that this string should be sorted to follow the other.<br/>
902 /// </returns>
903 public int CompareTo(FixedString512Bytes other)
904 {
905 return FixedStringMethods.CompareTo(ref this, other);
906 }
907
908
909 /// <summary>
910 /// Returns true if two strings are equal.
911 /// </summary>
912 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
913 /// <param name="a">A string to compare.</param>
914 /// <param name="b">Another string to compare.</param>
915 /// <returns>True if the two strings are equal.</returns>
916 public static bool operator ==(in NativeText a, in FixedString512Bytes b)
917 {
918 unsafe {
919 var aref = UnsafeUtilityExtensions.AsRef(a);
920 int alen = aref.Length;
921 int blen = b.utf8LengthInBytes;
922 byte* aptr = (byte*) aref.GetUnsafePtr();
923 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes);
924 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen);
925 }
926 }
927
928 /// <summary>
929 /// Returns true if two strings are unequal.
930 /// </summary>
931 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
932 /// <param name="a">A string to compare.</param>
933 /// <param name="b">Another string to compare.</param>
934 /// <returns>True if the two strings are unequal.</returns>
935 public static bool operator !=(in NativeText a, in FixedString512Bytes b)
936 {
937 return !(a == b);
938 }
939
940 /// <summary>
941 /// Returns true if this string and another are equal.
942 /// </summary>
943 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
944 /// <param name="other">Another string to compare with.</param>
945 /// <returns>True if the two strings are equal.</returns>
946 public bool Equals(FixedString512Bytes other)
947 {
948 return this == other;
949 }
950
951 /// <summary>
952 /// Returns the lexicographical sort order of this string relative to another.
953 /// </summary>
954 /// <param name="other">Another string to compare with.</param>
955 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
956 ///
957 /// 0 denotes both strings have the same sort position.<br/>
958 /// -1 denotes that this string should be sorted to precede the other.<br/>
959 /// +1 denotes that this string should be sorted to follow the other.<br/>
960 /// </returns>
961 public int CompareTo(FixedString4096Bytes other)
962 {
963 return FixedStringMethods.CompareTo(ref this, other);
964 }
965
966
967 /// <summary>
968 /// Returns true if two strings are equal.
969 /// </summary>
970 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
971 /// <param name="a">A string to compare.</param>
972 /// <param name="b">Another string to compare.</param>
973 /// <returns>True if the two strings are equal.</returns>
974 public static bool operator ==(in NativeText a, in FixedString4096Bytes b)
975 {
976 unsafe {
977 var aref = UnsafeUtilityExtensions.AsRef(a);
978 int alen = aref.Length;
979 int blen = b.utf8LengthInBytes;
980 byte* aptr = (byte*) aref.GetUnsafePtr();
981 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes);
982 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen);
983 }
984 }
985
986 /// <summary>
987 /// Returns true if two strings are unequal.
988 /// </summary>
989 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
990 /// <param name="a">A string to compare.</param>
991 /// <param name="b">Another string to compare.</param>
992 /// <returns>True if the two strings are unequal.</returns>
993 public static bool operator !=(in NativeText a, in FixedString4096Bytes b)
994 {
995 return !(a == b);
996 }
997
998 /// <summary>
999 /// Returns true if this string and another are equal.
1000 /// </summary>
1001 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1002 /// <param name="other">Another string to compare with.</param>
1003 /// <returns>True if the two strings are equal.</returns>
1004 public bool Equals(FixedString4096Bytes other)
1005 {
1006 return this == other;
1007 }
1008
1009 /// <summary>
1010 /// Returns a managed string copy of this string.
1011 /// </summary>
1012 /// <returns>A managed string copy of this string.</returns>
1013 [ExcludeFromBurstCompatTesting("Returns managed string")]
1014 public override String ToString()
1015 {
1016 if (m_Data == null)
1017 return "";
1018 CheckRead();
1019 return this.ConvertToString();
1020 }
1021
1022 /// <summary>
1023 /// Returns a hash code of this string.
1024 /// </summary>
1025 /// <remarks>The hash code is an integer that is always the same for two equal strings but (very likely) different for two unequal strings.</remarks>
1026 /// <returns>A hash code of this string.</returns>
1027 public override int GetHashCode()
1028 {
1029 return this.ComputeHashCode();
1030 }
1031
1032 /// <summary>
1033 /// Returns true if this string and another object are equal.
1034 /// </summary>
1035 /// <remarks>For the object to be equal, it must itself be a managed string, NativeText, or FixedString*N*Bytes.
1036 ///
1037 /// Two strings are equal if they have equal length and all their characters match.</remarks>
1038 /// <param name="other">Another string to compare with.</param>
1039 /// <returns>True if this string and the object are equal.</returns>
1040 [ExcludeFromBurstCompatTesting("Takes managed object")]
1041 public override bool Equals(object other)
1042 {
1043 if(ReferenceEquals(null, other)) return false;
1044 if(other is String aString) return Equals(aString);
1045 if(other is NativeText aNativeText) return Equals(aNativeText);
1046 if(other is ReadOnly aReadOnly) return Equals(aReadOnly);
1047 if(other is FixedString32Bytes a32) return Equals(a32);
1048 if(other is FixedString64Bytes a64) return Equals(a64);
1049 if(other is FixedString128Bytes a128) return Equals(a128);
1050 if(other is FixedString512Bytes a512) return Equals(a512);
1051 if(other is FixedString4096Bytes a4096) return Equals(a4096);
1052 return false;
1053 }
1054
1055 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")]
1056 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1057 internal static void CheckNull(void* dataPtr)
1058 {
1059 if (dataPtr == null)
1060 {
1061 throw new InvalidOperationException("NativeText has yet to be created or has been destroyed!");
1062 }
1063 }
1064
1065 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
1066 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1067 readonly void CheckRead()
1068 {
1069#if ENABLE_UNITY_COLLECTIONS_CHECKS
1070 AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
1071#endif
1072 }
1073
1074 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
1075 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1076 void CheckWrite()
1077 {
1078#if ENABLE_UNITY_COLLECTIONS_CHECKS
1079 AtomicSafetyHandle.CheckWriteAndThrow(m_Safety);
1080#endif
1081 }
1082
1083 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
1084 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1085 readonly void CheckWriteAndBumpSecondaryVersion()
1086 {
1087#if ENABLE_UNITY_COLLECTIONS_CHECKS
1088 AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion(m_Safety);
1089#endif
1090 }
1091
1092 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")]
1093 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1094 void CheckIndexInRange(int index)
1095 {
1096 if (index < 0)
1097 throw new IndexOutOfRangeException($"Index {index} must be positive.");
1098 if (index >= Length)
1099 throw new IndexOutOfRangeException($"Index {index} is out of range in NativeText of {Length} length.");
1100 }
1101
1102 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")]
1103 void ThrowCopyError(CopyError error, String source)
1104 {
1105 throw new ArgumentException($"NativeText: {error} while copying \"{source}\"");
1106 }
1107
1108 /// <summary>
1109 /// A read-only alias for the value of a NativeText. Does not have its own allocated storage.
1110 /// </summary>
1111 [NativeContainer]
1112 [NativeContainerIsReadOnly]
1113 public unsafe struct ReadOnly
1114 : INativeList<byte>
1115 , IUTF8Bytes
1116 , IComparable<String>
1117 , IEquatable<String>
1118 , IComparable<NativeText>
1119 , IEquatable<NativeText>
1120 , IComparable<FixedString32Bytes>
1121 , IEquatable<FixedString32Bytes>
1122 , IComparable<FixedString64Bytes>
1123 , IEquatable<FixedString64Bytes>
1124 , IComparable<FixedString128Bytes>
1125 , IEquatable<FixedString128Bytes>
1126 , IComparable<FixedString512Bytes>
1127 , IEquatable<FixedString512Bytes>
1128 , IComparable<FixedString4096Bytes>
1129 , IEquatable<FixedString4096Bytes>
1130 {
1131 [NativeDisableUnsafePtrRestriction]
1132 internal UnsafeText* m_Data;
1133
1134#if ENABLE_UNITY_COLLECTIONS_CHECKS
1135 internal AtomicSafetyHandle m_Safety;
1136 internal static readonly SharedStatic<int> s_staticSafetyId = SharedStatic<int>.GetOrCreate<NativeText.ReadOnly>();
1137
1138 internal ReadOnly(UnsafeText* text, AtomicSafetyHandle safety)
1139 {
1140 m_Data = text;
1141 m_Safety = safety;
1142 CollectionHelper.SetStaticSafetyId(ref m_Safety, ref s_staticSafetyId.Data, "Unity.Collections.NativeText.ReadOnly");
1143 }
1144#else
1145 internal ReadOnly(UnsafeText* text)
1146 {
1147 m_Data = text;
1148 }
1149#endif
1150
1151 /// <summary>
1152 /// The current capacity in bytes of this string.
1153 /// </summary>
1154 /// <remarks>
1155 /// The null-terminator byte is not included in the capacity, so the string's character buffer is `Capacity + 1` in size.
1156 /// </remarks>
1157 /// <value>The current capacity in bytes of the string.</value>
1158 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined and a write is attempted.</exception>
1159 public int Capacity
1160 {
1161 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1162 readonly get
1163 {
1164 CheckNull(m_Data);
1165 CheckRead();
1166 return m_Data->Capacity;
1167 }
1168
1169 set
1170 {
1171 ErrorWrite();
1172 }
1173 }
1174
1175 /// <summary>
1176 /// Whether this string has no characters.
1177 /// </summary>
1178 /// <value>True if this string has no characters or if the string has not been constructed.</value>
1179 public bool IsEmpty
1180 {
1181 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1182 readonly get
1183 {
1184 if (m_Data == null)
1185 {
1186 return true;
1187 }
1188
1189 CheckRead();
1190 return m_Data->IsEmpty;
1191 }
1192
1193 set
1194 {
1195 ErrorWrite();
1196 }
1197 }
1198
1199 /// <summary>
1200 /// The current length in bytes of this string.
1201 /// </summary>
1202 /// <remarks>
1203 /// The length does not include the null terminator byte.
1204 /// </remarks>
1205 /// <value>The current length in bytes of the UTF-8 encoded string.</value>
1206 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined and a write is attempted.</exception>
1207 public int Length
1208 {
1209 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1210 readonly get
1211 {
1212 CheckNull(m_Data);
1213 CheckRead();
1214 return m_Data->Length;
1215 }
1216 set
1217 {
1218 ErrorWrite();
1219 }
1220 }
1221
1222 /// <summary>
1223 /// The byte at an index.
1224 /// </summary>
1225 /// <param name="index">A zero-based byte index.</param>
1226 /// <value>The byte at the index.</value>
1227 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception>
1228 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined and a write is attempted.</exception>
1229 public byte this[int index]
1230 {
1231 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1232 readonly get
1233 {
1234 CheckNull(m_Data);
1235 CheckRead();
1236 return m_Data->ElementAt(index);
1237 }
1238
1239 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1240 set
1241 {
1242 ErrorWrite();
1243 }
1244 }
1245
1246 /// <summary>
1247 /// Sets the length to 0. For a NativeText.Readonly this function does nothing, unless safety checks are enabled (in which case it throws).
1248 /// </summary>
1249 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined.</exception>
1250 public void Clear()
1251 {
1252 ErrorWrite();
1253 }
1254
1255 /// <summary>
1256 /// Returns a reference to the byte (not character) at an index. Unsupported by NativeText.ReadOnly.
1257 /// </summary>
1258 /// <remarks>
1259 /// This function is a no-op when ENABLE_UNITY_COLLECTIONS_CHECKS is not defined, throws otherwise.
1260 /// </remarks>
1261 /// <param name="index">A byte index.</param>
1262 /// <returns>A reference to the byte at the index.</returns>
1263 /// <exception cref="NotSupportedException">Thrown when called. This operation is not supported.</exception>
1264 public ref byte ElementAt(int index)
1265 {
1266 throw new NotSupportedException("Trying to retrieve non-readonly ref to NativeText.ReadOnly data. This is not permitted.");
1267 }
1268
1269 /// <summary>
1270 /// Returns a pointer to this string's character buffer.
1271 /// </summary>
1272 /// <remarks>
1273 /// The pointer is made invalid by operations that reallocate the character buffer, such as setting <see cref="Capacity"/>.
1274 /// </remarks>
1275 /// <returns>A pointer to this string's character buffer.</returns>
1276 public byte* GetUnsafePtr()
1277 {
1278 CheckNull(m_Data);
1279 CheckRead();
1280 return m_Data->GetUnsafePtr();
1281 }
1282
1283 /// <summary>
1284 /// Attempt to set the length in bytes of this string. For NativeText.ReadOnly this function is a no-op and always returns false.
1285 /// </summary>
1286 /// <param name="newLength">The new length in bytes of the string.</param>
1287 /// <param name="clearOptions">Whether any bytes added should be zeroed out.</param>
1288 /// <returns>Always false.</returns>
1289 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined.</exception>
1290 public bool TryResize(int newLength, NativeArrayOptions clearOptions = NativeArrayOptions.ClearMemory)
1291 {
1292 ErrorWrite();
1293 return false;
1294 }
1295
1296 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")]
1297 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1298 internal static void CheckNull(void* dataPtr)
1299 {
1300 if (dataPtr == null)
1301 {
1302 throw new InvalidOperationException("NativeText.ReadOnly has yet to be created or has been destroyed!");
1303 }
1304 }
1305
1306 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
1307 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1308 readonly void CheckRead()
1309 {
1310#if ENABLE_UNITY_COLLECTIONS_CHECKS
1311 // Ensure we are allowed to read
1312 AtomicSafetyHandle.CheckReadAndThrow(m_Safety);
1313#endif
1314 }
1315
1316 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")]
1317 void ErrorWrite()
1318 {
1319 throw new NotSupportedException("Trying to write to a NativeText.ReadOnly. Write operations are not permitted and are ignored.");
1320 }
1321
1322 /// <summary>
1323 /// Returns the lexicographical sort order of this string relative to another.
1324 /// </summary>
1325 /// <param name="other">Another string to compare with.</param>
1326 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
1327 ///
1328 /// 0 denotes both strings have the same sort position.<br/>
1329 /// -1 denotes that this string should be sorted to precede the other.<br/>
1330 /// +1 denotes that this string should be sorted to follow the other.<br/>
1331 /// </returns>
1332 [ExcludeFromBurstCompatTesting("Takes managed string")]
1333 public int CompareTo(String other)
1334 {
1335 CheckNull(m_Data);
1336 CheckRead();
1337 return m_Data->ToString().CompareTo(other);
1338 }
1339
1340 /// <summary>
1341 /// Returns true if this string and another are equal.
1342 /// </summary>
1343 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1344 /// <param name="other">Another string to compare with.</param>
1345 /// <returns>True if the two strings are equal.</returns>
1346 [ExcludeFromBurstCompatTesting("Takes managed string")]
1347 public bool Equals(String other)
1348 {
1349 CheckNull(m_Data);
1350 CheckRead();
1351 return m_Data->ToString().Equals(other);
1352 }
1353
1354 /// <summary>
1355 /// Returns the lexicographical sort order of this string relative to another.
1356 /// </summary>
1357 /// <param name="other">Another string to compare with.</param>
1358 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
1359 ///
1360 /// 0 denotes both strings have the same sort position.<br/>
1361 /// -1 denotes that this string should be sorted to precede the other.<br/>
1362 /// +1 denotes that this string should be sorted to follow the other.<br/>
1363 /// </returns>
1364 public int CompareTo(ReadOnly other)
1365 {
1366 CheckNull(m_Data);
1367 CheckRead();
1368 return FixedStringMethods.CompareTo(ref *m_Data, *other.m_Data);
1369 }
1370
1371 /// <summary>
1372 /// Returns true if this string and another are equal.
1373 /// </summary>
1374 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1375 /// <param name="other">Another string to compare with.</param>
1376 /// <returns>True if the two strings are equal.</returns>
1377 public bool Equals(ReadOnly other)
1378 {
1379 CheckNull(m_Data);
1380 CheckRead();
1381 return FixedStringMethods.Equals(ref *m_Data, *other.m_Data);
1382 }
1383
1384 /// <summary>
1385 /// Returns the lexicographical sort order of this string relative to another.
1386 /// </summary>
1387 /// <param name="other">Another string to compare with.</param>
1388 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
1389 ///
1390 /// 0 denotes both strings have the same sort position.<br/>
1391 /// -1 denotes that this string should be sorted to precede the other.<br/>
1392 /// +1 denotes that this string should be sorted to follow the other.<br/>
1393 /// </returns>
1394 public int CompareTo(NativeText other)
1395 {
1396 CheckNull(m_Data);
1397 CheckRead();
1398 return FixedStringMethods.CompareTo(ref this, *other.m_Data);
1399 }
1400
1401 /// <summary>
1402 /// Returns true if this string and another are equal.
1403 /// </summary>
1404 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1405 /// <param name="other">Another string to compare with.</param>
1406 /// <returns>True if the two strings are equal.</returns>
1407 public bool Equals(NativeText other)
1408 {
1409 CheckNull(m_Data);
1410 CheckRead();
1411 return FixedStringMethods.Equals(ref this, *other.m_Data);
1412 }
1413
1414 /// <summary>
1415 /// Returns the lexicographical sort order of this string relative to another.
1416 /// </summary>
1417 /// <param name="other">Another string to compare with.</param>
1418 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
1419 ///
1420 /// 0 denotes both strings have the same sort position.<br/>
1421 /// -1 denotes that this string should be sorted to precede the other.<br/>
1422 /// +1 denotes that this string should be sorted to follow the other.<br/>
1423 /// </returns>
1424 public int CompareTo(FixedString32Bytes other)
1425 {
1426 return FixedStringMethods.CompareTo(ref this, other);
1427 }
1428
1429
1430 /// <summary>
1431 /// Returns true if two strings are equal.
1432 /// </summary>
1433 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1434 /// <param name="a">A string to compare.</param>
1435 /// <param name="b">Another string to compare.</param>
1436 /// <returns>True if the two strings are equal.</returns>
1437 public static bool operator ==(in ReadOnly a, in FixedString32Bytes b)
1438 {
1439 CheckNull(a.m_Data);
1440 a.CheckRead();
1441 unsafe {
1442 var aref = *a.m_Data;
1443 int alen = aref.Length;
1444 int blen = b.utf8LengthInBytes;
1445 byte* aptr = (byte*) aref.GetUnsafePtr();
1446 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes);
1447 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen);
1448 }
1449 }
1450
1451 /// <summary>
1452 /// Returns true if two strings are unequal.
1453 /// </summary>
1454 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1455 /// <param name="a">A string to compare.</param>
1456 /// <param name="b">Another string to compare.</param>
1457 /// <returns>True if the two strings are unequal.</returns>
1458 public static bool operator !=(in ReadOnly a, in FixedString32Bytes b)
1459 {
1460 return !(a == b);
1461 }
1462
1463 /// <summary>
1464 /// Returns true if this string and another are equal.
1465 /// </summary>
1466 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1467 /// <param name="other">Another string to compare with.</param>
1468 /// <returns>True if the two strings are equal.</returns>
1469 public bool Equals(FixedString32Bytes other)
1470 {
1471 return this == other;
1472 }
1473 /// <summary>
1474 /// Returns the lexicographical sort order of this string relative to another.
1475 /// </summary>
1476 /// <param name="other">Another string to compare with.</param>
1477 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
1478 ///
1479 /// 0 denotes both strings have the same sort position.<br/>
1480 /// -1 denotes that this string should be sorted to precede the other.<br/>
1481 /// +1 denotes that this string should be sorted to follow the other.<br/>
1482 /// </returns>
1483 public int CompareTo(FixedString64Bytes other)
1484 {
1485 return FixedStringMethods.CompareTo(ref this, other);
1486 }
1487
1488
1489 /// <summary>
1490 /// Returns true if two strings are equal.
1491 /// </summary>
1492 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1493 /// <param name="a">A string to compare.</param>
1494 /// <param name="b">Another string to compare.</param>
1495 /// <returns>True if the two strings are equal.</returns>
1496 public static bool operator ==(in ReadOnly a, in FixedString64Bytes b)
1497 {
1498 CheckNull(a.m_Data);
1499 a.CheckRead();
1500 unsafe {
1501 var aref = *a.m_Data;
1502 int alen = aref.Length;
1503 int blen = b.utf8LengthInBytes;
1504 byte* aptr = (byte*) aref.GetUnsafePtr();
1505 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes);
1506 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen);
1507 }
1508 }
1509
1510 /// <summary>
1511 /// Returns true if two strings are unequal.
1512 /// </summary>
1513 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1514 /// <param name="a">A string to compare.</param>
1515 /// <param name="b">Another string to compare.</param>
1516 /// <returns>True if the two strings are unequal.</returns>
1517 public static bool operator !=(in ReadOnly a, in FixedString64Bytes b)
1518 {
1519 return !(a == b);
1520 }
1521
1522 /// <summary>
1523 /// Returns true if this string and another are equal.
1524 /// </summary>
1525 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1526 /// <param name="other">Another string to compare with.</param>
1527 /// <returns>True if the two strings are equal.</returns>
1528 public bool Equals(FixedString64Bytes other)
1529 {
1530 return this == other;
1531 }
1532 /// <summary>
1533 /// Returns the lexicographical sort order of this string relative to another.
1534 /// </summary>
1535 /// <param name="other">Another string to compare with.</param>
1536 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
1537 ///
1538 /// 0 denotes both strings have the same sort position.<br/>
1539 /// -1 denotes that this string should be sorted to precede the other.<br/>
1540 /// +1 denotes that this string should be sorted to follow the other.<br/>
1541 /// </returns>
1542 public int CompareTo(FixedString128Bytes other)
1543 {
1544 return FixedStringMethods.CompareTo(ref this, other);
1545 }
1546
1547
1548 /// <summary>
1549 /// Returns true if two strings are equal.
1550 /// </summary>
1551 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1552 /// <param name="a">A string to compare.</param>
1553 /// <param name="b">Another string to compare.</param>
1554 /// <returns>True if the two strings are equal.</returns>
1555 public static bool operator ==(in ReadOnly a, in FixedString128Bytes b)
1556 {
1557 CheckNull(a.m_Data);
1558 a.CheckRead();
1559 unsafe {
1560 var aref = *a.m_Data;
1561 int alen = aref.Length;
1562 int blen = b.utf8LengthInBytes;
1563 byte* aptr = (byte*) aref.GetUnsafePtr();
1564 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes);
1565 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen);
1566 }
1567 }
1568
1569 /// <summary>
1570 /// Returns true if two strings are unequal.
1571 /// </summary>
1572 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1573 /// <param name="a">A string to compare.</param>
1574 /// <param name="b">Another string to compare.</param>
1575 /// <returns>True if the two strings are unequal.</returns>
1576 public static bool operator !=(in ReadOnly a, in FixedString128Bytes b)
1577 {
1578 return !(a == b);
1579 }
1580
1581 /// <summary>
1582 /// Returns true if this string and another are equal.
1583 /// </summary>
1584 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1585 /// <param name="other">Another string to compare with.</param>
1586 /// <returns>True if the two strings are equal.</returns>
1587 public bool Equals(FixedString128Bytes other)
1588 {
1589 return this == other;
1590 }
1591 /// <summary>
1592 /// Returns the lexicographical sort order of this string relative to another.
1593 /// </summary>
1594 /// <param name="other">Another string to compare with.</param>
1595 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
1596 ///
1597 /// 0 denotes both strings have the same sort position.<br/>
1598 /// -1 denotes that this string should be sorted to precede the other.<br/>
1599 /// +1 denotes that this string should be sorted to follow the other.<br/>
1600 /// </returns>
1601 public int CompareTo(FixedString512Bytes other)
1602 {
1603 return FixedStringMethods.CompareTo(ref this, other);
1604 }
1605
1606
1607 /// <summary>
1608 /// Returns true if two strings are equal.
1609 /// </summary>
1610 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1611 /// <param name="a">A string to compare.</param>
1612 /// <param name="b">Another string to compare.</param>
1613 /// <returns>True if the two strings are equal.</returns>
1614 public static bool operator ==(in ReadOnly a, in FixedString512Bytes b)
1615 {
1616 CheckNull(a.m_Data);
1617 a.CheckRead();
1618 unsafe {
1619 var aref = *a.m_Data;
1620 int alen = aref.Length;
1621 int blen = b.utf8LengthInBytes;
1622 byte* aptr = (byte*) aref.GetUnsafePtr();
1623 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes);
1624 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen);
1625 }
1626 }
1627
1628 /// <summary>
1629 /// Returns true if two strings are unequal.
1630 /// </summary>
1631 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1632 /// <param name="a">A string to compare.</param>
1633 /// <param name="b">Another string to compare.</param>
1634 /// <returns>True if the two strings are unequal.</returns>
1635 public static bool operator !=(in ReadOnly a, in FixedString512Bytes b)
1636 {
1637 return !(a == b);
1638 }
1639
1640 /// <summary>
1641 /// Returns true if this string and another are equal.
1642 /// </summary>
1643 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1644 /// <param name="other">Another string to compare with.</param>
1645 /// <returns>True if the two strings are equal.</returns>
1646 public bool Equals(FixedString512Bytes other)
1647 {
1648 return this == other;
1649 }
1650 /// <summary>
1651 /// Returns the lexicographical sort order of this string relative to another.
1652 /// </summary>
1653 /// <param name="other">Another string to compare with.</param>
1654 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string:
1655 ///
1656 /// 0 denotes both strings have the same sort position.<br/>
1657 /// -1 denotes that this string should be sorted to precede the other.<br/>
1658 /// +1 denotes that this string should be sorted to follow the other.<br/>
1659 /// </returns>
1660 public int CompareTo(FixedString4096Bytes other)
1661 {
1662 return FixedStringMethods.CompareTo(ref this, other);
1663 }
1664
1665
1666 /// <summary>
1667 /// Returns true if two strings are equal.
1668 /// </summary>
1669 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1670 /// <param name="a">A string to compare.</param>
1671 /// <param name="b">Another string to compare.</param>
1672 /// <returns>True if the two strings are equal.</returns>
1673 public static bool operator ==(in ReadOnly a, in FixedString4096Bytes b)
1674 {
1675 CheckNull(a.m_Data);
1676 a.CheckRead();
1677 unsafe {
1678 var aref = *a.m_Data;
1679 int alen = aref.Length;
1680 int blen = b.utf8LengthInBytes;
1681 byte* aptr = (byte*) aref.GetUnsafePtr();
1682 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes);
1683 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen);
1684 }
1685 }
1686
1687 /// <summary>
1688 /// Returns true if two strings are unequal.
1689 /// </summary>
1690 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1691 /// <param name="a">A string to compare.</param>
1692 /// <param name="b">Another string to compare.</param>
1693 /// <returns>True if the two strings are unequal.</returns>
1694 public static bool operator !=(in ReadOnly a, in FixedString4096Bytes b)
1695 {
1696 return !(a == b);
1697 }
1698
1699 /// <summary>
1700 /// Returns true if this string and another are equal.
1701 /// </summary>
1702 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks>
1703 /// <param name="other">Another string to compare with.</param>
1704 /// <returns>True if the two strings are equal.</returns>
1705 public bool Equals(FixedString4096Bytes other)
1706 {
1707 return this == other;
1708 }
1709
1710 /// <summary>
1711 /// Returns a managed string copy of this string.
1712 /// </summary>
1713 /// <returns>A managed string copy of this string.</returns>
1714 [ExcludeFromBurstCompatTesting("Returns managed string")]
1715 public override String ToString()
1716 {
1717 if (m_Data == null)
1718 return "";
1719 CheckRead();
1720 return this.ConvertToString();
1721 }
1722
1723 /// <summary>
1724 /// Returns a hash code of this string.
1725 /// </summary>
1726 /// <remarks>The hash code is an integer that is always the same for two equal strings but (very likely) different for two unequal strings.</remarks>
1727 /// <returns>A hash code of this string.</returns>
1728 public override int GetHashCode()
1729 {
1730 CheckRead();
1731 return this.ComputeHashCode();
1732 }
1733
1734 /// <summary>
1735 /// Returns true if this string and another object are equal.
1736 /// </summary>
1737 /// <remarks>For the object to be equal, it must itself be a managed string, NativeText, or FixedString*N*Bytes.
1738 ///
1739 /// Two strings are equal if they have equal length and all their characters match.</remarks>
1740 /// <param name="other">Another string to compare with.</param>
1741 /// <returns>True if this string and the object are equal.</returns>
1742 [ExcludeFromBurstCompatTesting("Takes managed object")]
1743 public override bool Equals(object other)
1744 {
1745 if(ReferenceEquals(null, other)) return false;
1746 if(other is String aString) return Equals(aString);
1747 if(other is NativeText aNativeText) return Equals(aNativeText);
1748 if(other is ReadOnly aReadOnly) return Equals(aReadOnly);
1749 if(other is FixedString32Bytes a32) return Equals(a32);
1750 if(other is FixedString64Bytes a64) return Equals(a64);
1751 if(other is FixedString128Bytes a128) return Equals(a128);
1752 if(other is FixedString512Bytes a512) return Equals(a512);
1753 if(other is FixedString4096Bytes a4096) return Equals(a4096);
1754 return false;
1755 }
1756
1757 /// <summary>
1758 /// A copy of this string as a managed string.
1759 /// </summary>
1760 /// <remarks>
1761 /// For internal use only. Use <see cref="ToString"/> instead.
1762 /// </remarks>
1763 /// <value>A copy of this string as a managed string.</value>
1764 [CreateProperty]
1765 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
1766 [ExcludeFromBurstCompatTesting("Returns managed string")]
1767 public string Value => ToString();
1768
1769 /// <summary>
1770 /// Returns an enumerator for iterating over the characters of the NativeText.
1771 /// </summary>
1772 /// <returns>An enumerator for iterating over the characters of the NativeText.</returns>
1773 public Enumerator GetEnumerator()
1774 {
1775 return new Enumerator(this);
1776 }
1777 }
1778
1779 /// <summary>
1780 /// Returns a readonly version of this NativeText instance.
1781 /// </summary>
1782 /// <remarks>ReadOnly containers point to the same underlying data as the NativeText it is made from. Note while ReadOnly contains methods that would write to the string data these methods will perform no writes and/or throw a NotSupportedException.</remarks>
1783 /// <returns>ReadOnly instance for this.</returns>
1784 public ReadOnly AsReadOnly()
1785 {
1786#if ENABLE_UNITY_COLLECTIONS_CHECKS
1787 var ash = m_Safety;
1788 return new ReadOnly(m_Data, ash);
1789#else
1790 return new ReadOnly(m_Data);
1791#endif
1792 }
1793 }
1794
1795 [NativeContainer]
1796 [GenerateTestsForBurstCompatibility]
1797 internal unsafe struct NativeTextDispose
1798 {
1799 [NativeDisableUnsafePtrRestriction]
1800 public UnsafeText* m_TextData;
1801
1802#if ENABLE_UNITY_COLLECTIONS_CHECKS
1803 public AtomicSafetyHandle m_Safety;
1804#endif
1805
1806 public void Dispose()
1807 {
1808 UnsafeText.Free(m_TextData);
1809 }
1810 }
1811
1812 [BurstCompile]
1813 internal unsafe struct NativeTextDisposeJob : IJob
1814 {
1815 public NativeTextDispose Data;
1816
1817 public void Execute()
1818 {
1819 Data.Dispose();
1820 }
1821 }
1822}