A game about forced loneliness, made by TACStudios
1<#@ template language="C#" debug="True" #> 2<#@ output extension=".gen.cs" encoding="utf-8" #> 3<#@ assembly name="System.Core" #> 4 5//------------------------------------------------------------------------------ 6// <auto-generated> 7// This code was generated by a tool. 8// 9// TextTransform Packages/com.unity.collections/Unity.Collections/NativeText.tt 10// 11// Changes to this file may cause incorrect behavior and will be lost if 12// the code is regenerated. 13// </auto-generated> 14//------------------------------------------------------------------------------ 15 16using System; 17using System.Collections; 18using System.Collections.Generic; 19using System.Diagnostics; 20using System.Runtime.InteropServices; 21using System.Runtime.CompilerServices; 22using Unity.Burst; 23using Unity.Collections.LowLevel.Unsafe; 24using Unity.Jobs; 25using UnityEngine.Internal; 26using Unity.Properties; 27 28<# 29{ 30 var SIZES = new [] {32,64,128,512,4096}; 31#> 32 33 34namespace Unity.Collections 35{ 36 /// <summary> 37 /// An unmanaged, mutable, resizable UTF-8 string. 38 /// </summary> 39 /// <remarks> 40 /// The string is always null-terminated, meaning a zero byte always immediately follows the last character. 41 /// </remarks> 42 [StructLayout(LayoutKind.Sequential)] 43 [NativeContainer] 44 [DebuggerDisplay("Length = {Length}")] 45 [GenerateTestsForBurstCompatibility] 46 public unsafe partial struct NativeText 47 : INativeList<byte> 48 , INativeDisposable 49 , IUTF8Bytes 50 , IComparable<String> 51 , IEquatable<String> 52 , IComparable<NativeText> 53 , IEquatable<NativeText> 54<# 55 foreach (var OTHERBYTES in SIZES) 56 { 57#> 58 , IComparable<FixedString<#=OTHERBYTES#>Bytes> 59 , IEquatable<FixedString<#=OTHERBYTES#>Bytes> 60<# 61 } 62#> 63 { 64#if ENABLE_UNITY_COLLECTIONS_CHECKS 65 internal AtomicSafetyHandle m_Safety; 66 internal static readonly SharedStatic<int> s_staticSafetyId = SharedStatic<int>.GetOrCreate<NativeText>(); 67#endif 68 // NOTE! This Length is always > 0, because we have a null terminating byte. 69 // We hide this byte from NativeText users. 70 [NativeDisableUnsafePtrRestriction] 71 internal UnsafeText* m_Data; 72 73 /// <summary> 74 /// Initializes and returns an instance of NativeText with the characters copied from another string. 75 /// </summary> 76 /// <param name="source">A string to copy characters from.</param> 77 /// <param name="allocator">The allocator to use.</param> 78 [ExcludeFromBurstCompatTesting("Takes managed string")] 79 public NativeText(String source, Allocator allocator) : this(source, (AllocatorManager.AllocatorHandle)allocator) 80 { 81 } 82 83 /// <summary> 84 /// Initializes and returns an instance of NativeText with the characters copied from another string. 85 /// </summary> 86 /// <param name="source">A string to copy characters from.</param> 87 /// <param name="allocator">The allocator to use.</param> 88 [ExcludeFromBurstCompatTesting("Takes managed string")] 89 public NativeText(String source, AllocatorManager.AllocatorHandle allocator) : this(source.Length * 2, allocator) 90 { 91 Length = source.Length * 2; 92 unsafe 93 { 94 fixed (char* sourceptr = source) 95 { 96 var error = UTF8ArrayUnsafeUtility.Copy(GetUnsafePtr(), out var actualBytes, Capacity, sourceptr, source.Length); 97 if (error != CopyError.None) 98 { 99 CheckNull(m_Data); 100 m_Data->Dispose(); 101 m_Data = UnsafeText.Alloc(allocator); 102 *m_Data = default(UnsafeText); 103 ThrowCopyError(error, source); 104 } 105 Length = actualBytes; 106 } 107 } 108 109#if ENABLE_UNITY_COLLECTIONS_CHECKS 110 CollectionHelper.SetStaticSafetyId(ref m_Safety, ref s_staticSafetyId.Data, "Unity.Collections.NativeText"); 111 112 AtomicSafetyHandle.SetBumpSecondaryVersionOnScheduleWrite(m_Safety, true); 113#endif 114 } 115 116 /// <summary> 117 /// Initializes and returns an instance of NativeText. 118 /// </summary> 119 /// <param name="capacity">The initial capacity in bytes.</param> 120 /// <param name="allocator">The allocator to use.</param> 121 public NativeText(int capacity, Allocator allocator) : this(capacity, (AllocatorManager.AllocatorHandle)allocator) 122 { 123 } 124 125 /// <summary> 126 /// Initializes and returns an instance of NativeText. 127 /// </summary> 128 /// <param name="capacity">The initial capacity in bytes.</param> 129 /// <param name="allocator">The allocator to use.</param> 130 public NativeText(int capacity, AllocatorManager.AllocatorHandle allocator) 131 { 132#if ENABLE_UNITY_COLLECTIONS_CHECKS 133 CollectionHelper.CheckAllocator(allocator); 134 135 m_Safety = CollectionHelper.CreateSafetyHandle(allocator); 136 137 CollectionHelper.SetStaticSafetyId(ref m_Safety, ref s_staticSafetyId.Data, "Unity.Collections.NativeText"); 138 139 AtomicSafetyHandle.SetBumpSecondaryVersionOnScheduleWrite(m_Safety, true); 140#endif 141 m_Data = UnsafeText.Alloc(allocator); 142 *m_Data = new UnsafeText(capacity, allocator); 143 } 144 145 /// <summary> 146 /// Initializes and returns an instance of NativeText with an initial capacity of 512 bytes. 147 /// </summary> 148 /// <param name="allocator">The allocator to use.</param> 149 public NativeText(Allocator allocator) : this((AllocatorManager.AllocatorHandle)allocator) 150 { 151 } 152 153 /// <summary> 154 /// Initializes and returns an instance of NativeText with an initial capacity of 512 bytes. 155 /// </summary> 156 /// <param name="allocator">The allocator to use.</param> 157 public NativeText(AllocatorManager.AllocatorHandle allocator) : this(512, allocator) 158 { 159 } 160 161<# 162 foreach(var OTHERBYTES in SIZES) 163 { 164#> 165 /// <summary> 166 /// Initializes and returns an instance of NativeText with the characters copied from another string. 167 /// </summary> 168 /// <param name="source">A string to copy characters from.</param> 169 /// <param name="allocator">The allocator to use.</param> 170 public NativeText(in FixedString<#=OTHERBYTES#>Bytes source, AllocatorManager.AllocatorHandle allocator) 171 : this(source.utf8LengthInBytes, allocator) 172 { 173 Length = source.utf8LengthInBytes; 174 unsafe { 175 byte* sbytes = (byte*) UnsafeUtilityExtensions.AddressOf(source.bytes); 176 byte* dbytes = (byte*) m_Data->GetUnsafePtr(); 177 UnsafeUtility.MemCpy(dbytes, sbytes, source.utf8LengthInBytes); 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 FixedString<#=OTHERBYTES#>Bytes source, Allocator allocator) 187 : this(source, (AllocatorManager.AllocatorHandle)allocator) 188 { 189 } 190 191<# 192 } 193#> 194 195 /// <summary> 196 /// The current length in bytes of this string. 197 /// </summary> 198 /// <remarks> 199 /// The length does not include the null terminator byte. 200 /// </remarks> 201 /// <value>The current length in bytes of the UTF-8 encoded string.</value> 202 public int Length 203 { 204 [MethodImpl(MethodImplOptions.AggressiveInlining)] 205 readonly get 206 { 207 CheckNull(m_Data); 208 CheckRead(); 209 return m_Data->Length; 210 } 211 212 set 213 { 214 CheckNull(m_Data); 215 CheckWriteAndBumpSecondaryVersion(); 216 m_Data->Length = value; 217 } 218 } 219 220 /// <summary> 221 /// The current capacity in bytes of this string. 222 /// </summary> 223 /// <remarks> 224 /// The null-terminator byte is not included in the capacity, so the string's character buffer is `Capacity + 1` in size. 225 /// </remarks> 226 /// <value>The current capacity in bytes of the string.</value> 227 public int Capacity 228 { 229 [MethodImpl(MethodImplOptions.AggressiveInlining)] 230 readonly get 231 { 232 CheckNull(m_Data); 233 CheckRead(); 234 return m_Data->Capacity; 235 } 236 237 set 238 { 239 CheckNull(m_Data); 240 CheckWriteAndBumpSecondaryVersion(); 241 m_Data->Capacity = value; 242 } 243 } 244 245 /// <summary> 246 /// Attempt to set the length in bytes of this string. 247 /// </summary> 248 /// <param name="newLength">The new length in bytes of the string.</param> 249 /// <param name="clearOptions">Whether any bytes added should be zeroed out.</param> 250 /// <returns>Always true.</returns> 251 public bool TryResize(int newLength, NativeArrayOptions clearOptions = NativeArrayOptions.ClearMemory) 252 { 253 CheckWrite(); 254 255 // this can't ever fail, because if we can't resize malloc will abort 256 Length = newLength; 257 return true; 258 } 259 260 /// <summary> 261 /// Whether this string has no characters. 262 /// </summary> 263 /// <value>True if this string has no characters or the string has not been constructed.</value> 264 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined and a write is attempted.</exception> 265 public readonly bool IsEmpty 266 { 267 [MethodImpl(MethodImplOptions.AggressiveInlining)] 268 get 269 { 270 if (!IsCreated) 271 { 272 return true; 273 } 274 275 CheckRead(); 276 return m_Data->IsEmpty; 277 } 278 } 279 280 /// <summary> 281 /// Whether this string's character buffer has been allocated (and not yet deallocated). 282 /// </summary> 283 /// <value>Whether this string's character buffer has been allocated (and not yet deallocated).</value> 284 public readonly bool IsCreated 285 { 286 [MethodImpl(MethodImplOptions.AggressiveInlining)] 287 get => m_Data != null; 288 } 289 290 /// <summary> 291 /// Returns a pointer to this string's character buffer. 292 /// </summary> 293 /// <remarks> 294 /// The pointer is made invalid by operations that reallocate the character buffer, such as setting <see cref="Capacity"/>. 295 /// </remarks> 296 /// <returns>A pointer to this string's character buffer.</returns> 297 public unsafe byte* GetUnsafePtr() 298 { 299 CheckNull(m_Data); 300 CheckRead(); 301 return m_Data->GetUnsafePtr(); 302 } 303 304 /// <summary> 305 /// 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. 306 /// </summary> 307 /// <param name="index">A zero-based byte index.</param> 308 /// <value>The byte at the index.</value> 309 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception> 310 public byte this[int index] 311 { 312 [MethodImpl(MethodImplOptions.AggressiveInlining)] 313 get 314 { 315 CheckNull(m_Data); 316 CheckRead(); 317 return m_Data->ElementAt(index); 318 } 319 [MethodImpl(MethodImplOptions.AggressiveInlining)] 320 set 321 { 322 CheckNull(m_Data); 323 CheckWrite(); 324 m_Data->ElementAt(index) = value; 325 } 326 } 327 328 /// <summary> 329 /// Returns a reference to the byte (not character) at an index. 330 /// </summary> 331 /// <remarks> 332 /// Deallocating or reallocating this string's character buffer makes the reference invalid. 333 /// </remarks> 334 /// <param name="index">A byte index.</param> 335 /// <returns>A reference to the byte at the index.</returns> 336 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception> 337 [MethodImpl(MethodImplOptions.AggressiveInlining)] 338 public ref byte ElementAt(int index) 339 { 340 CheckNull(m_Data); 341 CheckWrite(); 342 return ref m_Data->ElementAt(index); 343 } 344 345 /// <summary> 346 /// Sets the length to 0. 347 /// </summary> 348 public void Clear() 349 { 350 Length = 0; 351 } 352 353 /// <summary> 354 /// Appends a byte. 355 /// </summary> 356 /// <remarks> 357 /// A zero byte will always follow the newly appended byte. 358 /// 359 /// 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. 360 /// </remarks> 361 /// <param name="value">A byte to append.</param> 362 [MethodImpl(MethodImplOptions.AggressiveInlining)] 363 public void Add(in byte value) 364 { 365 CheckWrite(); 366 this[Length++] = value; 367 } 368 369 /// <summary> 370 /// Returns the lexicographical sort order of this string relative to another. 371 /// </summary> 372 /// <param name="other">Another string to compare with.</param> 373 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string: 374 /// 375 /// 0 denotes both strings have the same sort position.<br/> 376 /// -1 denotes that this string should be sorted to precede the other.<br/> 377 /// +1 denotes that this string should be sorted to follow the other.<br/> 378 /// </returns> 379 public int CompareTo(NativeText other) 380 { 381 CheckRead(); 382 return FixedStringMethods.CompareTo(ref this, *other.m_Data); 383 } 384 385 /// <summary> 386 /// Returns true if this string and another are equal. 387 /// </summary> 388 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 389 /// <param name="other">Another string to compare with.</param> 390 /// <returns>True if the two strings are equal.</returns> 391 public bool Equals(NativeText other) 392 { 393 CheckRead(); 394 return FixedStringMethods.Equals(ref this, *other.m_Data); 395 } 396 397 /// <summary> 398 /// Returns the lexicographical sort order of this string relative to another. 399 /// </summary> 400 /// <param name="other">Another string to compare with.</param> 401 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string: 402 /// 403 /// 0 denotes both strings have the same sort position.<br/> 404 /// -1 denotes that this string should be sorted to precede the other.<br/> 405 /// +1 denotes that this string should be sorted to follow the other.<br/> 406 /// </returns> 407 public int CompareTo(NativeText.ReadOnly other) 408 { 409 CheckRead(); 410 return FixedStringMethods.CompareTo(ref this, other); 411 } 412 413 /// <summary> 414 /// Returns true if this string and another are equal. 415 /// </summary> 416 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 417 /// <param name="other">Another string to compare with.</param> 418 /// <returns>True if the two strings are equal.</returns> 419 public bool Equals(NativeText.ReadOnly other) 420 { 421 CheckRead(); 422 return FixedStringMethods.Equals(ref this, *other.m_Data); 423 } 424 425 /// <summary> 426 /// Releases all resources (memory and safety handles). 427 /// </summary> 428 public void Dispose() 429 { 430#if ENABLE_UNITY_COLLECTIONS_CHECKS 431 if (!AtomicSafetyHandle.IsDefaultValue(m_Safety)) 432 { 433 AtomicSafetyHandle.CheckExistsAndThrow(m_Safety); 434 } 435#endif 436 if (!IsCreated) 437 { 438 return; 439 } 440 441#if ENABLE_UNITY_COLLECTIONS_CHECKS 442 CollectionHelper.DisposeSafetyHandle(ref m_Safety); 443#endif 444 UnsafeText.Free(m_Data); 445 m_Data = null; 446 } 447 448 /// <summary> 449 /// Creates and schedules a job that releases all resources (memory and safety handles) of this NativeText. 450 /// </summary> 451 /// <param name="inputDeps">The dependency for the new job.</param> 452 /// <returns>The handle of the new job. The job depends upon `inputDeps` and releases all resources (memory and safety handles) of this NativeText.</returns> 453 public JobHandle Dispose(JobHandle inputDeps) 454 { 455#if ENABLE_UNITY_COLLECTIONS_CHECKS 456 if (!AtomicSafetyHandle.IsDefaultValue(m_Safety)) 457 { 458 AtomicSafetyHandle.CheckExistsAndThrow(m_Safety); 459 } 460#endif 461 if (!IsCreated) 462 { 463 return inputDeps; 464 } 465 466#if ENABLE_UNITY_COLLECTIONS_CHECKS 467 var jobHandle = new NativeTextDisposeJob { Data = new NativeTextDispose { m_TextData = m_Data, m_Safety = m_Safety } }.Schedule(inputDeps); 468 AtomicSafetyHandle.Release(m_Safety); 469#else 470 var jobHandle = new NativeTextDisposeJob { Data = new NativeTextDispose { m_TextData = m_Data } }.Schedule(inputDeps); 471#endif 472 m_Data = null; 473 474 return jobHandle; 475 } 476 477 /// <summary> 478 /// A copy of this string as a managed string. 479 /// </summary> 480 /// <remarks> 481 /// For internal use only. Use <see cref="ToString"/> instead. 482 /// </remarks> 483 /// <value>A copy of this string as a managed string.</value> 484 [CreateProperty] 485 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] 486 [ExcludeFromBurstCompatTesting("Returns managed string")] 487 public string Value => ToString(); 488 489 /// <summary> 490 /// An enumerator over the characters (not bytes) of a NativeText. 491 /// </summary> 492 /// <remarks> 493 /// 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. 494 /// </remarks> 495 public struct Enumerator : IEnumerator<Unicode.Rune> 496 { 497 NativeText.ReadOnly target; 498 int offset; 499 Unicode.Rune current; 500 501 /// <summary> 502 /// Initializes and returns an instance of NativeText.Enumerator. 503 /// </summary> 504 /// <param name="source">A NativeText for which to create an enumerator.</param> 505 public Enumerator(NativeText source) 506 { 507#if ENABLE_UNITY_COLLECTIONS_CHECKS 508 AtomicSafetyHandle.CheckGetSecondaryDataPointerAndThrow(source.m_Safety); 509 510 var ash = source.m_Safety; 511 AtomicSafetyHandle.UseSecondaryVersion(ref ash); 512 513 target = new ReadOnly(source.m_Data, ash); 514#else 515 target = source.AsReadOnly(); 516#endif 517 offset = 0; 518 current = default; 519 } 520 521 522 /// <summary> 523 /// Initializes and returns an instance of NativeText.Enumerator. 524 /// </summary> 525 /// <param name="source">A NativeText.ReadOnly for which to create an enumerator.</param> 526 public Enumerator(NativeText.ReadOnly source) 527 { 528#if ENABLE_UNITY_COLLECTIONS_CHECKS 529 AtomicSafetyHandle.CheckGetSecondaryDataPointerAndThrow(source.m_Safety); 530 531 var ash = source.m_Safety; 532 AtomicSafetyHandle.UseSecondaryVersion(ref ash); 533 534 target = new ReadOnly(source.m_Data, ash); 535#else 536 target = source; 537#endif 538 offset = 0; 539 current = default; 540 } 541 542 /// <summary> 543 /// Does nothing. 544 /// </summary> 545 public void Dispose() 546 { 547 } 548 549 /// <summary> 550 /// Advances the enumerator to the next character, returning true if <see cref="Current"/> is valid to read afterwards. 551 /// </summary> 552 /// <returns>True if <see cref="Current"/> is valid to read after the call.</returns> 553 [MethodImpl(MethodImplOptions.AggressiveInlining)] 554 public bool MoveNext() 555 { 556 if (offset >= target.Length) 557 return false; 558 559 unsafe 560 { 561 Unicode.Utf8ToUcs(out current, target.GetUnsafePtr(), ref offset, target.Length); 562 } 563 564 return true; 565 } 566 567 /// <summary> 568 /// Resets the enumerator to its initial state. 569 /// </summary> 570 public void Reset() 571 { 572 offset = 0; 573 current = default; 574 } 575 576 object IEnumerator.Current 577 { 578 [MethodImpl(MethodImplOptions.AggressiveInlining)] 579 get => Current; 580 } 581 582 /// <summary> 583 /// The current character. 584 /// </summary> 585 /// <value>The current character.</value> 586 public Unicode.Rune Current => current; 587 } 588 589 /// <summary> 590 /// Returns an enumerator for iterating over the characters of the NativeText. 591 /// </summary> 592 /// <returns>An enumerator for iterating over the characters of the NativeText.</returns> 593 public Enumerator GetEnumerator() 594 { 595 return new Enumerator(this); 596 } 597 598 /// <summary> 599 /// Returns the lexicographical sort order of this string relative to another. 600 /// </summary> 601 /// <param name="other">Another string to compare with.</param> 602 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string: 603 /// 604 /// 0 denotes both strings have the same sort position.<br/> 605 /// -1 denotes that this string should be sorted to precede the other.<br/> 606 /// +1 denotes that this string should be sorted to follow the other.<br/> 607 /// </returns> 608 [ExcludeFromBurstCompatTesting("Takes managed string")] 609 public int CompareTo(String other) 610 { 611 return ToString().CompareTo(other); 612 } 613 614 /// <summary> 615 /// Returns true if this string and another are equal. 616 /// </summary> 617 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 618 /// <param name="other">Another string to compare with.</param> 619 /// <returns>True if the two strings are equal.</returns> 620 [ExcludeFromBurstCompatTesting("Takes managed string")] 621 public bool Equals(String other) 622 { 623 return ToString().Equals(other); 624 } 625 626 627<# 628 // 629 // Generate easy conversion and comparison between this and other FixedString types 630 // 631 foreach (var OTHERBYTES in SIZES) 632 { 633#> 634 635 /// <summary> 636 /// Returns the lexicographical sort order of this string relative to another. 637 /// </summary> 638 /// <param name="other">Another string to compare with.</param> 639 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string: 640 /// 641 /// 0 denotes both strings have the same sort position.<br/> 642 /// -1 denotes that this string should be sorted to precede the other.<br/> 643 /// +1 denotes that this string should be sorted to follow the other.<br/> 644 /// </returns> 645 public int CompareTo(FixedString<#=OTHERBYTES#>Bytes other) 646 { 647 return FixedStringMethods.CompareTo(ref this, other); 648 } 649 650 651 /// <summary> 652 /// Returns true if two strings are equal. 653 /// </summary> 654 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 655 /// <param name="a">A string to compare.</param> 656 /// <param name="b">Another string to compare.</param> 657 /// <returns>True if the two strings are equal.</returns> 658 public static bool operator ==(in NativeText a, in FixedString<#=OTHERBYTES#>Bytes b) 659 { 660 unsafe { 661 var aref = UnsafeUtilityExtensions.AsRef(a); 662 int alen = aref.Length; 663 int blen = b.utf8LengthInBytes; 664 byte* aptr = (byte*) aref.GetUnsafePtr(); 665 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes); 666 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen); 667 } 668 } 669 670 /// <summary> 671 /// Returns true if two strings are unequal. 672 /// </summary> 673 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 674 /// <param name="a">A string to compare.</param> 675 /// <param name="b">Another string to compare.</param> 676 /// <returns>True if the two strings are unequal.</returns> 677 public static bool operator !=(in NativeText a, in FixedString<#=OTHERBYTES#>Bytes b) 678 { 679 return !(a == b); 680 } 681 682 /// <summary> 683 /// Returns true if this string and another are equal. 684 /// </summary> 685 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 686 /// <param name="other">Another string to compare with.</param> 687 /// <returns>True if the two strings are equal.</returns> 688 public bool Equals(FixedString<#=OTHERBYTES#>Bytes other) 689 { 690 return this == other; 691 } 692<# 693 } 694#> 695 696 /// <summary> 697 /// Returns a managed string copy of this string. 698 /// </summary> 699 /// <returns>A managed string copy of this string.</returns> 700 [ExcludeFromBurstCompatTesting("Returns managed string")] 701 public override String ToString() 702 { 703 if (m_Data == null) 704 return ""; 705 CheckRead(); 706 return this.ConvertToString(); 707 } 708 709 /// <summary> 710 /// Returns a hash code of this string. 711 /// </summary> 712 /// <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> 713 /// <returns>A hash code of this string.</returns> 714 public override int GetHashCode() 715 { 716 return this.ComputeHashCode(); 717 } 718 719 /// <summary> 720 /// Returns true if this string and another object are equal. 721 /// </summary> 722 /// <remarks>For the object to be equal, it must itself be a managed string, NativeText, or FixedString*N*Bytes. 723 /// 724 /// Two strings are equal if they have equal length and all their characters match.</remarks> 725 /// <param name="other">Another string to compare with.</param> 726 /// <returns>True if this string and the object are equal.</returns> 727 [ExcludeFromBurstCompatTesting("Takes managed object")] 728 public override bool Equals(object other) 729 { 730 if(ReferenceEquals(null, other)) return false; 731 if(other is String aString) return Equals(aString); 732 if(other is NativeText aNativeText) return Equals(aNativeText); 733 if(other is ReadOnly aReadOnly) return Equals(aReadOnly); 734<# 735 foreach(var OTHERBYTES in SIZES) 736 { 737#> 738 if(other is FixedString<#=OTHERBYTES#>Bytes a<#=OTHERBYTES#>) return Equals(a<#=OTHERBYTES#>); 739<# 740 } 741#> 742 return false; 743 } 744 745 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")] 746 [MethodImpl(MethodImplOptions.AggressiveInlining)] 747 internal static void CheckNull(void* dataPtr) 748 { 749 if (dataPtr == null) 750 { 751 throw new InvalidOperationException("NativeText has yet to be created or has been destroyed!"); 752 } 753 } 754 755 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] 756 [MethodImpl(MethodImplOptions.AggressiveInlining)] 757 readonly void CheckRead() 758 { 759#if ENABLE_UNITY_COLLECTIONS_CHECKS 760 AtomicSafetyHandle.CheckReadAndThrow(m_Safety); 761#endif 762 } 763 764 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] 765 [MethodImpl(MethodImplOptions.AggressiveInlining)] 766 void CheckWrite() 767 { 768#if ENABLE_UNITY_COLLECTIONS_CHECKS 769 AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); 770#endif 771 } 772 773 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] 774 [MethodImpl(MethodImplOptions.AggressiveInlining)] 775 readonly void CheckWriteAndBumpSecondaryVersion() 776 { 777#if ENABLE_UNITY_COLLECTIONS_CHECKS 778 AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion(m_Safety); 779#endif 780 } 781 782 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")] 783 [MethodImpl(MethodImplOptions.AggressiveInlining)] 784 void CheckIndexInRange(int index) 785 { 786 if (index < 0) 787 throw new IndexOutOfRangeException($"Index {index} must be positive."); 788 if (index >= Length) 789 throw new IndexOutOfRangeException($"Index {index} is out of range in NativeText of {Length} length."); 790 } 791 792 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")] 793 void ThrowCopyError(CopyError error, String source) 794 { 795 throw new ArgumentException($"NativeText: {error} while copying \"{source}\""); 796 } 797 798 /// <summary> 799 /// A read-only alias for the value of a NativeText. Does not have its own allocated storage. 800 /// </summary> 801 [NativeContainer] 802 [NativeContainerIsReadOnly] 803 public unsafe struct ReadOnly 804 : INativeList<byte> 805 , IUTF8Bytes 806 , IComparable<String> 807 , IEquatable<String> 808 , IComparable<NativeText> 809 , IEquatable<NativeText> 810<# 811 foreach (var OTHERBYTES in SIZES) 812 { 813#> 814 , IComparable<FixedString<#=OTHERBYTES#>Bytes> 815 , IEquatable<FixedString<#=OTHERBYTES#>Bytes> 816<# 817 } 818#> 819 { 820 [NativeDisableUnsafePtrRestriction] 821 internal UnsafeText* m_Data; 822 823#if ENABLE_UNITY_COLLECTIONS_CHECKS 824 internal AtomicSafetyHandle m_Safety; 825 internal static readonly SharedStatic<int> s_staticSafetyId = SharedStatic<int>.GetOrCreate<NativeText.ReadOnly>(); 826 827 internal ReadOnly(UnsafeText* text, AtomicSafetyHandle safety) 828 { 829 m_Data = text; 830 m_Safety = safety; 831 CollectionHelper.SetStaticSafetyId(ref m_Safety, ref s_staticSafetyId.Data, "Unity.Collections.NativeText.ReadOnly"); 832 } 833#else 834 internal ReadOnly(UnsafeText* text) 835 { 836 m_Data = text; 837 } 838#endif 839 840 /// <summary> 841 /// The current capacity in bytes of this string. 842 /// </summary> 843 /// <remarks> 844 /// The null-terminator byte is not included in the capacity, so the string's character buffer is `Capacity + 1` in size. 845 /// </remarks> 846 /// <value>The current capacity in bytes of the string.</value> 847 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined and a write is attempted.</exception> 848 public int Capacity 849 { 850 [MethodImpl(MethodImplOptions.AggressiveInlining)] 851 readonly get 852 { 853 CheckNull(m_Data); 854 CheckRead(); 855 return m_Data->Capacity; 856 } 857 858 set 859 { 860 ErrorWrite(); 861 } 862 } 863 864 /// <summary> 865 /// Whether this string has no characters. 866 /// </summary> 867 /// <value>True if this string has no characters or if the string has not been constructed.</value> 868 public bool IsEmpty 869 { 870 [MethodImpl(MethodImplOptions.AggressiveInlining)] 871 readonly get 872 { 873 if (m_Data == null) 874 { 875 return true; 876 } 877 878 CheckRead(); 879 return m_Data->IsEmpty; 880 } 881 882 set 883 { 884 ErrorWrite(); 885 } 886 } 887 888 /// <summary> 889 /// The current length in bytes of this string. 890 /// </summary> 891 /// <remarks> 892 /// The length does not include the null terminator byte. 893 /// </remarks> 894 /// <value>The current length in bytes of the UTF-8 encoded string.</value> 895 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined and a write is attempted.</exception> 896 public int Length 897 { 898 [MethodImpl(MethodImplOptions.AggressiveInlining)] 899 readonly get 900 { 901 CheckNull(m_Data); 902 CheckRead(); 903 return m_Data->Length; 904 } 905 set 906 { 907 ErrorWrite(); 908 } 909 } 910 911 /// <summary> 912 /// The byte at an index. 913 /// </summary> 914 /// <param name="index">A zero-based byte index.</param> 915 /// <value>The byte at the index.</value> 916 /// <exception cref="IndexOutOfRangeException">Thrown if the index is out of bounds.</exception> 917 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined and a write is attempted.</exception> 918 public byte this[int index] 919 { 920 [MethodImpl(MethodImplOptions.AggressiveInlining)] 921 readonly get 922 { 923 CheckNull(m_Data); 924 CheckRead(); 925 return m_Data->ElementAt(index); 926 } 927 928 [MethodImpl(MethodImplOptions.AggressiveInlining)] 929 set 930 { 931 ErrorWrite(); 932 } 933 } 934 935 /// <summary> 936 /// Sets the length to 0. For a NativeText.Readonly this function does nothing, unless safety checks are enabled (in which case it throws). 937 /// </summary> 938 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined.</exception> 939 public void Clear() 940 { 941 ErrorWrite(); 942 } 943 944 /// <summary> 945 /// Returns a reference to the byte (not character) at an index. Unsupported by NativeText.ReadOnly. 946 /// </summary> 947 /// <remarks> 948 /// This function is a no-op when ENABLE_UNITY_COLLECTIONS_CHECKS is not defined, throws otherwise. 949 /// </remarks> 950 /// <param name="index">A byte index.</param> 951 /// <returns>A reference to the byte at the index.</returns> 952 /// <exception cref="NotSupportedException">Thrown when called. This operation is not supported.</exception> 953 public ref byte ElementAt(int index) 954 { 955 throw new NotSupportedException("Trying to retrieve non-readonly ref to NativeText.ReadOnly data. This is not permitted."); 956 } 957 958 /// <summary> 959 /// Returns a pointer to this string's character buffer. 960 /// </summary> 961 /// <remarks> 962 /// The pointer is made invalid by operations that reallocate the character buffer, such as setting <see cref="Capacity"/>. 963 /// </remarks> 964 /// <returns>A pointer to this string's character buffer.</returns> 965 public byte* GetUnsafePtr() 966 { 967 CheckNull(m_Data); 968 CheckRead(); 969 return m_Data->GetUnsafePtr(); 970 } 971 972 /// <summary> 973 /// Attempt to set the length in bytes of this string. For NativeText.ReadOnly this function is a no-op and always returns false. 974 /// </summary> 975 /// <param name="newLength">The new length in bytes of the string.</param> 976 /// <param name="clearOptions">Whether any bytes added should be zeroed out.</param> 977 /// <returns>Always false.</returns> 978 /// <exception cref="NotSupportedException">Thrown if ENABLE_UNITY_COLLECTIONS_CHECKS is defined.</exception> 979 public bool TryResize(int newLength, NativeArrayOptions clearOptions = NativeArrayOptions.ClearMemory) 980 { 981 ErrorWrite(); 982 return false; 983 } 984 985 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")] 986 [MethodImpl(MethodImplOptions.AggressiveInlining)] 987 internal static void CheckNull(void* dataPtr) 988 { 989 if (dataPtr == null) 990 { 991 throw new InvalidOperationException("NativeText.ReadOnly has yet to be created or has been destroyed!"); 992 } 993 } 994 995 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] 996 [MethodImpl(MethodImplOptions.AggressiveInlining)] 997 readonly void CheckRead() 998 { 999#if ENABLE_UNITY_COLLECTIONS_CHECKS 1000 // Ensure we are allowed to read 1001 AtomicSafetyHandle.CheckReadAndThrow(m_Safety); 1002#endif 1003 } 1004 1005 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")] 1006 void ErrorWrite() 1007 { 1008 throw new NotSupportedException("Trying to write to a NativeText.ReadOnly. Write operations are not permitted and are ignored."); 1009 } 1010 1011 /// <summary> 1012 /// Returns the lexicographical sort order of this string relative to another. 1013 /// </summary> 1014 /// <param name="other">Another string to compare with.</param> 1015 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string: 1016 /// 1017 /// 0 denotes both strings have the same sort position.<br/> 1018 /// -1 denotes that this string should be sorted to precede the other.<br/> 1019 /// +1 denotes that this string should be sorted to follow the other.<br/> 1020 /// </returns> 1021 [ExcludeFromBurstCompatTesting("Takes managed string")] 1022 public int CompareTo(String other) 1023 { 1024 CheckNull(m_Data); 1025 CheckRead(); 1026 return m_Data->ToString().CompareTo(other); 1027 } 1028 1029 /// <summary> 1030 /// Returns true if this string and another are equal. 1031 /// </summary> 1032 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 1033 /// <param name="other">Another string to compare with.</param> 1034 /// <returns>True if the two strings are equal.</returns> 1035 [ExcludeFromBurstCompatTesting("Takes managed string")] 1036 public bool Equals(String other) 1037 { 1038 CheckNull(m_Data); 1039 CheckRead(); 1040 return m_Data->ToString().Equals(other); 1041 } 1042 1043 /// <summary> 1044 /// Returns the lexicographical sort order of this string relative to another. 1045 /// </summary> 1046 /// <param name="other">Another string to compare with.</param> 1047 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string: 1048 /// 1049 /// 0 denotes both strings have the same sort position.<br/> 1050 /// -1 denotes that this string should be sorted to precede the other.<br/> 1051 /// +1 denotes that this string should be sorted to follow the other.<br/> 1052 /// </returns> 1053 public int CompareTo(ReadOnly other) 1054 { 1055 CheckNull(m_Data); 1056 CheckRead(); 1057 return FixedStringMethods.CompareTo(ref *m_Data, *other.m_Data); 1058 } 1059 1060 /// <summary> 1061 /// Returns true if this string and another are equal. 1062 /// </summary> 1063 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 1064 /// <param name="other">Another string to compare with.</param> 1065 /// <returns>True if the two strings are equal.</returns> 1066 public bool Equals(ReadOnly other) 1067 { 1068 CheckNull(m_Data); 1069 CheckRead(); 1070 return FixedStringMethods.Equals(ref *m_Data, *other.m_Data); 1071 } 1072 1073 /// <summary> 1074 /// Returns the lexicographical sort order of this string relative to another. 1075 /// </summary> 1076 /// <param name="other">Another string to compare with.</param> 1077 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string: 1078 /// 1079 /// 0 denotes both strings have the same sort position.<br/> 1080 /// -1 denotes that this string should be sorted to precede the other.<br/> 1081 /// +1 denotes that this string should be sorted to follow the other.<br/> 1082 /// </returns> 1083 public int CompareTo(NativeText other) 1084 { 1085 CheckNull(m_Data); 1086 CheckRead(); 1087 return FixedStringMethods.CompareTo(ref this, *other.m_Data); 1088 } 1089 1090 /// <summary> 1091 /// Returns true if this string and another are equal. 1092 /// </summary> 1093 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 1094 /// <param name="other">Another string to compare with.</param> 1095 /// <returns>True if the two strings are equal.</returns> 1096 public bool Equals(NativeText other) 1097 { 1098 CheckNull(m_Data); 1099 CheckRead(); 1100 return FixedStringMethods.Equals(ref this, *other.m_Data); 1101 } 1102 1103<# 1104 // 1105 // Generate easy conversion and comparison between this and other FixedString types 1106 // 1107 foreach (var OTHERBYTES in SIZES) 1108 { 1109#> 1110 /// <summary> 1111 /// Returns the lexicographical sort order of this string relative to another. 1112 /// </summary> 1113 /// <param name="other">Another string to compare with.</param> 1114 /// <returns>A number denoting the lexicographical sort order of this string relative to the other string: 1115 /// 1116 /// 0 denotes both strings have the same sort position.<br/> 1117 /// -1 denotes that this string should be sorted to precede the other.<br/> 1118 /// +1 denotes that this string should be sorted to follow the other.<br/> 1119 /// </returns> 1120 public int CompareTo(FixedString<#=OTHERBYTES#>Bytes other) 1121 { 1122 return FixedStringMethods.CompareTo(ref this, other); 1123 } 1124 1125 1126 /// <summary> 1127 /// Returns true if two strings are equal. 1128 /// </summary> 1129 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 1130 /// <param name="a">A string to compare.</param> 1131 /// <param name="b">Another string to compare.</param> 1132 /// <returns>True if the two strings are equal.</returns> 1133 public static bool operator ==(in ReadOnly a, in FixedString<#=OTHERBYTES#>Bytes b) 1134 { 1135 CheckNull(a.m_Data); 1136 a.CheckRead(); 1137 unsafe { 1138 var aref = *a.m_Data; 1139 int alen = aref.Length; 1140 int blen = b.utf8LengthInBytes; 1141 byte* aptr = (byte*) aref.GetUnsafePtr(); 1142 byte* bptr = (byte*) UnsafeUtilityExtensions.AddressOf(b.bytes); 1143 return UTF8ArrayUnsafeUtility.EqualsUTF8Bytes(aptr, alen, bptr, blen); 1144 } 1145 } 1146 1147 /// <summary> 1148 /// Returns true if two strings are unequal. 1149 /// </summary> 1150 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 1151 /// <param name="a">A string to compare.</param> 1152 /// <param name="b">Another string to compare.</param> 1153 /// <returns>True if the two strings are unequal.</returns> 1154 public static bool operator !=(in ReadOnly a, in FixedString<#=OTHERBYTES#>Bytes b) 1155 { 1156 return !(a == b); 1157 } 1158 1159 /// <summary> 1160 /// Returns true if this string and another are equal. 1161 /// </summary> 1162 /// <remarks>Two strings are equal if they have equal length and all their characters match.</remarks> 1163 /// <param name="other">Another string to compare with.</param> 1164 /// <returns>True if the two strings are equal.</returns> 1165 public bool Equals(FixedString<#=OTHERBYTES#>Bytes other) 1166 { 1167 return this == other; 1168 } 1169<# 1170 } 1171#> 1172 1173 /// <summary> 1174 /// Returns a managed string copy of this string. 1175 /// </summary> 1176 /// <returns>A managed string copy of this string.</returns> 1177 [ExcludeFromBurstCompatTesting("Returns managed string")] 1178 public override String ToString() 1179 { 1180 if (m_Data == null) 1181 return ""; 1182 CheckRead(); 1183 return this.ConvertToString(); 1184 } 1185 1186 /// <summary> 1187 /// Returns a hash code of this string. 1188 /// </summary> 1189 /// <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> 1190 /// <returns>A hash code of this string.</returns> 1191 public override int GetHashCode() 1192 { 1193 CheckRead(); 1194 return this.ComputeHashCode(); 1195 } 1196 1197 /// <summary> 1198 /// Returns true if this string and another object are equal. 1199 /// </summary> 1200 /// <remarks>For the object to be equal, it must itself be a managed string, NativeText, or FixedString*N*Bytes. 1201 /// 1202 /// Two strings are equal if they have equal length and all their characters match.</remarks> 1203 /// <param name="other">Another string to compare with.</param> 1204 /// <returns>True if this string and the object are equal.</returns> 1205 [ExcludeFromBurstCompatTesting("Takes managed object")] 1206 public override bool Equals(object other) 1207 { 1208 if(ReferenceEquals(null, other)) return false; 1209 if(other is String aString) return Equals(aString); 1210 if(other is NativeText aNativeText) return Equals(aNativeText); 1211 if(other is ReadOnly aReadOnly) return Equals(aReadOnly); 1212<# 1213 foreach(var OTHERBYTES in SIZES) 1214 { 1215#> 1216 if(other is FixedString<#=OTHERBYTES#>Bytes a<#=OTHERBYTES#>) return Equals(a<#=OTHERBYTES#>); 1217<# 1218 } 1219#> 1220 return false; 1221 } 1222 1223 /// <summary> 1224 /// A copy of this string as a managed string. 1225 /// </summary> 1226 /// <remarks> 1227 /// For internal use only. Use <see cref="ToString"/> instead. 1228 /// </remarks> 1229 /// <value>A copy of this string as a managed string.</value> 1230 [CreateProperty] 1231 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] 1232 [ExcludeFromBurstCompatTesting("Returns managed string")] 1233 public string Value => ToString(); 1234 1235 /// <summary> 1236 /// Returns an enumerator for iterating over the characters of the NativeText. 1237 /// </summary> 1238 /// <returns>An enumerator for iterating over the characters of the NativeText.</returns> 1239 public Enumerator GetEnumerator() 1240 { 1241 return new Enumerator(this); 1242 } 1243 } 1244 1245 /// <summary> 1246 /// Returns a readonly version of this NativeText instance. 1247 /// </summary> 1248 /// <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> 1249 /// <returns>ReadOnly instance for this.</returns> 1250 public ReadOnly AsReadOnly() 1251 { 1252#if ENABLE_UNITY_COLLECTIONS_CHECKS 1253 var ash = m_Safety; 1254 return new ReadOnly(m_Data, ash); 1255#else 1256 return new ReadOnly(m_Data); 1257#endif 1258 } 1259 } 1260 1261 [NativeContainer] 1262 [GenerateTestsForBurstCompatibility] 1263 internal unsafe struct NativeTextDispose 1264 { 1265 [NativeDisableUnsafePtrRestriction] 1266 public UnsafeText* m_TextData; 1267 1268#if ENABLE_UNITY_COLLECTIONS_CHECKS 1269 public AtomicSafetyHandle m_Safety; 1270#endif 1271 1272 public void Dispose() 1273 { 1274 UnsafeText.Free(m_TextData); 1275 } 1276 } 1277 1278 [BurstCompile] 1279 internal unsafe struct NativeTextDisposeJob : IJob 1280 { 1281 public NativeTextDispose Data; 1282 1283 public void Execute() 1284 { 1285 Data.Dispose(); 1286 } 1287 } 1288} 1289<#}#>