66namespace PolylineAlgorithm ;
77
88using System ;
9+ using System . Buffers ;
910using System . Collections . Generic ;
1011using System . Diagnostics ;
1112using System . Diagnostics . CodeAnalysis ;
13+ using System . Globalization ;
1214using System . Runtime . InteropServices ;
15+ using System . Text ;
1316
1417/// <summary>
1518/// Represents a readonly encoded polyline string.
1619/// </summary>
1720[ StructLayout ( LayoutKind . Auto ) ]
1821[ DebuggerDisplay ( "Value: {ToString()}, IsEmpty: {IsEmpty}, Length: {Length}" ) ]
1922public readonly struct Polyline : IEquatable < Polyline > {
20- private readonly ReadOnlyMemory < char > _value ;
23+ private readonly ReadOnlySequence < char > _value ;
2124
2225 /// <summary>
2326 /// Creates a new <see cref="Polyline"/> structure that is empty.
2427 /// </summary>
2528 public Polyline ( ) {
26- _value = ReadOnlyMemory < char > . Empty ;
29+ _value = ReadOnlySequence < char > . Empty ;
2730 }
2831
2932 /// <summary>
@@ -36,7 +39,7 @@ public Polyline(string value) {
3639 throw new ArgumentNullException ( nameof ( value ) ) ;
3740 }
3841
39- _value = value . AsMemory ( ) ;
42+ _value = new ReadOnlySequence < char > ( value . AsMemory ( ) ) ;
4043 }
4144
4245 /// <summary>
@@ -49,21 +52,21 @@ public Polyline(char[] value) {
4952 throw new ArgumentNullException ( nameof ( value ) ) ;
5053 }
5154
52- _value = _value = value . AsMemory ( ) ;
55+ _value = new ReadOnlySequence < char > ( value . AsMemory ( ) ) ;
5356 }
5457
5558 /// <summary>
5659 /// Creates a new <see cref="Polyline"/> structure that contains the specified readonly memory region.
5760 /// </summary>
5861 /// <param name="value">The readonly memory region to initialize the polyline with.</param>
5962 public Polyline ( ReadOnlyMemory < char > value ) {
60- _value = value ;
63+ _value = new ReadOnlySequence < char > ( value ) ;
6164 }
6265
6366 /// <summary>
6467 /// Gets the span of characters in the polyline.
6568 /// </summary>
66- internal readonly ReadOnlyMemory < char > Value => _value ;
69+ internal readonly ReadOnlySequence < char > Value => _value ;
6770
6871 /// <summary>
6972 /// Gets a value indicating whether this <see cref="Polyline" /> is empty.
@@ -79,24 +82,57 @@ public Polyline(ReadOnlyMemory<char> value) {
7982 /// Copies the characters in this instance to a Unicode character array.
8083 /// </summary>
8184 /// <returns>A Unicode character array.</returns>
82- public char [ ] ToCharArray ( ) => Value . ToArray ( ) ;
85+ public char [ ] CopyTo ( char [ ] destination ) {
86+ if ( destination is null ) {
87+ throw new ArgumentNullException ( nameof ( destination ) ) ;
88+ }
8389
84- /// <summary>
85- /// Returns a string representation of the value of this instance.
86- /// </summary>
87- /// <returns>The string value of this <see cref="Polyline"/> object.</returns>
88- public override string ToString ( ) => Value . ToString ( ) ;
90+ if ( Length != destination . Length ) {
91+ throw new ArgumentException ( "" , paramName : nameof ( destination ) ) ;
92+ }
93+
94+ _value . CopyTo ( destination ) ;
8995
90- public ReadOnlyMemory < char > AsMemory ( ) => Value ;
96+ return destination ;
97+ }
98+
99+ public ReadOnlySequence < char > AsSequence ( ) => Value ;
100+
101+ public override string ToString ( ) {
102+ if ( IsEmpty ) {
103+ return string . Empty ;
104+ }
91105
92- public Polyline Append ( ReadOnlyMemory < char > value ) {
93- if ( value . IsEmpty ) {
94- return this ;
106+ if ( Value . IsSingleSegment ) {
107+ return Value . FirstSpan . ToString ( ) ;
108+ }
109+
110+ var sb = Value . Length <= int . MaxValue ? new StringBuilder ( Convert . ToInt32 ( Value . Length ) ) : new StringBuilder ( ) ;
111+ var enumerator = Value . GetEnumerator ( ) ;
112+
113+ while ( true ) {
114+ if ( ! enumerator . MoveNext ( ) ) {
115+ break ;
116+ }
117+
118+ if ( enumerator . Current . IsEmpty ) {
119+ continue ;
120+ }
121+
122+ sb . Append ( enumerator . Current ) ;
123+ }
124+
125+ return sb . ToString ( ) ;
126+ }
127+
128+ public bool Equals ( Polyline other ) {
129+ if ( ( IsEmpty != other . IsEmpty ) || ( Length != other . Length ) ) {
130+ return false ;
95131 }
96132
97133 long position = 0 ;
98134 var enumerator = Value . GetEnumerator ( ) ;
99- var right = new SequenceReader < byte > ( other . Value ) ;
135+ var right = new SequenceReader < char > ( other . Value ) ;
100136
101137 while ( true ) {
102138 if ( ! enumerator . MoveNext ( ) ) {
@@ -117,6 +153,22 @@ public Polyline Append(ReadOnlyMemory<char> value) {
117153 return position == right . Length ;
118154 }
119155
156+ public override bool Equals ( object obj ) {
157+ return obj is Polyline other && Equals ( other ) ;
158+ }
159+
160+ public override int GetHashCode ( ) {
161+ return Value . GetHashCode ( ) ;
162+ }
163+
164+ public static bool operator == ( Polyline left , Polyline right ) {
165+ return left . Equals ( right ) ;
166+ }
167+
168+ public static bool operator != ( Polyline left , Polyline right ) {
169+ return ! ( left == right ) ;
170+ }
171+
120172 #region Factory methods
121173
122174 /// <summary>
@@ -140,10 +192,6 @@ public Polyline Append(ReadOnlyMemory<char> value) {
140192 /// <returns>The <see cref="Polyline"/> value that corresponds to the specified string value.</returns>
141193 public static Polyline FromString ( string polyline ) => new ( polyline ) ;
142194
143- internal void Append ( IEnumerable < char > latitude , IEnumerable < char > longitude ) {
144- throw new NotImplementedException ( ) ;
145- }
146-
147195 #endregion
148196
149197 #region Explicit conversions
0 commit comments