Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
BlobBuilder.cs
Go to the documentation of this file.
5using System.IO;
9
11
12[DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
13public class BlobBuilder
14{
15 internal struct Chunks : IEnumerable<BlobBuilder>, IEnumerable, IEnumerator<BlobBuilder>, IEnumerator, IDisposable
16 {
17 private readonly BlobBuilder _head;
18
20
22
23 object IEnumerator.Current => Current;
24
26
28 {
29 _head = builder;
30 _next = builder.FirstChunk;
31 _currentOpt = null;
32 }
33
34 public bool MoveNext()
35 {
36 if (_currentOpt == _head)
37 {
38 return false;
39 }
41 {
43 return true;
44 }
47 return true;
48 }
49
50 public void Reset()
51 {
52 _currentOpt = null;
54 }
55
57 {
58 }
59
61 {
62 return this;
63 }
64
69
74 }
75
77 {
78 private Chunks _chunks;
79
80 object IEnumerator.Current => Current;
81
83 {
84 get
85 {
86 BlobBuilder current = _chunks.Current;
87 if (current != null)
88 {
89 return new Blob(current._buffer, 0, current.Length);
90 }
91 return default(Blob);
92 }
93 }
94
96 {
97 _chunks = new Chunks(builder);
98 }
99
100 public bool MoveNext()
101 {
102 return _chunks.MoveNext();
103 }
104
105 public void Reset()
106 {
107 _chunks.Reset();
108 }
109
111 {
112 }
113
115 {
116 return this;
117 }
118
123
128 }
129
130 internal const int DefaultChunkSize = 256;
131
132 internal const int MinChunkSize = 16;
133
135
137
138 private byte[] _buffer;
139
140 private uint _length;
141
143
144 private bool IsHead => (_length & 0x80000000u) == 0;
145
146 private int Length => (int)(_length & 0x7FFFFFFF);
147
148 private uint FrozenLength => _length | 0x80000000u;
149
151
152 private int PreviousLength
153 {
154 get
155 {
157 }
158 set
159 {
161 }
162 }
163
164 protected int FreeBytes => _buffer.Length - Length;
165
166 protected internal int ChunkCapacity => _buffer.Length;
167
168 public BlobBuilder(int capacity = 256)
169 {
170 if (capacity < 0)
171 {
172 Throw.ArgumentOutOfRange("capacity");
173 }
174 _nextOrPrevious = this;
175 _buffer = new byte[Math.Max(16, capacity)];
176 }
177
178 protected virtual BlobBuilder AllocateChunk(int minimalSize)
179 {
180 return new BlobBuilder(Math.Max(_buffer.Length, minimalSize));
181 }
182
183 protected virtual void FreeChunk()
184 {
185 }
186
187 public void Clear()
188 {
189 if (!IsHead)
190 {
192 }
194 if (firstChunk != this)
195 {
196 byte[] buffer = firstChunk._buffer;
197 firstChunk._length = FrozenLength;
198 firstChunk._buffer = _buffer;
199 _buffer = buffer;
200 }
201 foreach (BlobBuilder chunk in GetChunks())
202 {
203 if (chunk != this)
204 {
205 chunk.ClearChunk();
206 chunk.FreeChunk();
207 }
208 }
209 ClearChunk();
210 }
211
212 protected void Free()
213 {
214 Clear();
215 FreeChunk();
216 }
217
218 internal void ClearChunk()
219 {
220 _length = 0u;
222 _nextOrPrevious = this;
223 }
224
225 private void CheckInvariants()
226 {
227 }
228
229 internal Chunks GetChunks()
230 {
231 if (!IsHead)
232 {
234 }
235 return new Chunks(this);
236 }
237
239 {
240 if (!IsHead)
241 {
243 }
244 return new Blobs(this);
245 }
246
248 {
249 if (!IsHead)
250 {
252 }
253 if (this == other)
254 {
255 return true;
256 }
257 if (other == null)
258 {
259 return false;
260 }
261 if (!other.IsHead)
262 {
264 }
265 if (Count != other.Count)
266 {
267 return false;
268 }
270 Chunks chunks2 = other.GetChunks();
271 int num = 0;
272 int num2 = 0;
273 bool flag = chunks.MoveNext();
274 bool flag2 = chunks2.MoveNext();
275 while (flag && flag2)
276 {
277 BlobBuilder current = chunks.Current;
278 BlobBuilder current2 = chunks2.Current;
279 int num3 = Math.Min(current.Length - num, current2.Length - num2);
280 if (!ByteSequenceComparer.Equals(current._buffer, num, current2._buffer, num2, num3))
281 {
282 return false;
283 }
284 num += num3;
285 num2 += num3;
286 if (num == current.Length)
287 {
288 flag = chunks.MoveNext();
289 num = 0;
290 }
291 if (num2 == current2.Length)
292 {
293 flag2 = chunks2.MoveNext();
294 num2 = 0;
295 }
296 }
297 return flag == flag2;
298 }
299
300 public byte[] ToArray()
301 {
302 return ToArray(0, Count);
303 }
304
305 public byte[] ToArray(int start, int byteCount)
306 {
308 byte[] array = new byte[byteCount];
309 int num = 0;
310 int num2 = start;
311 int num3 = start + byteCount;
312 foreach (BlobBuilder chunk in GetChunks())
313 {
314 int num4 = num + chunk.Length;
315 if (num4 > num2)
316 {
317 int num5 = Math.Min(num3, num4) - num2;
318 Array.Copy(chunk._buffer, num2 - num, array, num2 - start, num5);
319 num2 += num5;
320 if (num2 == num3)
321 {
322 break;
323 }
324 }
325 num = num4;
326 }
327 return array;
328 }
329
331 {
332 return ToImmutableArray(0, Count);
333 }
334
340
342 {
343 if (destination == null)
344 {
345 Throw.ArgumentNull("destination");
346 }
347 foreach (BlobBuilder chunk in GetChunks())
348 {
349 destination.Write(chunk._buffer, 0, chunk.Length);
350 }
351 }
352
354 {
355 if (destination.IsDefault)
356 {
357 Throw.ArgumentNull("destination");
358 }
359 foreach (BlobBuilder chunk in GetChunks())
360 {
361 destination.WriteBytes(chunk._buffer, 0, chunk.Length);
362 }
363 }
364
366 {
367 if (destination == null)
368 {
369 Throw.ArgumentNull("destination");
370 }
371 foreach (BlobBuilder chunk in GetChunks())
372 {
373 destination.WriteBytes(chunk._buffer, 0, chunk.Length);
374 }
375 }
376
378 {
379 if (prefix == null)
380 {
381 Throw.ArgumentNull("prefix");
382 }
383 if (!prefix.IsHead || !IsHead)
384 {
386 }
387 if (prefix.Count != 0)
388 {
389 PreviousLength += prefix.Count;
390 prefix._length = prefix.FrozenLength;
392 BlobBuilder firstChunk2 = prefix.FirstChunk;
394 BlobBuilder nextOrPrevious2 = prefix._nextOrPrevious;
396 prefix._nextOrPrevious = ((firstChunk != this) ? firstChunk : ((firstChunk2 != prefix) ? firstChunk2 : prefix));
397 if (nextOrPrevious != this)
398 {
399 nextOrPrevious._nextOrPrevious = ((firstChunk2 != prefix) ? firstChunk2 : prefix);
400 }
401 if (nextOrPrevious2 != prefix)
402 {
403 nextOrPrevious2._nextOrPrevious = prefix;
404 }
407 }
408 }
409
411 {
412 if (suffix == null)
413 {
414 throw new ArgumentNullException("suffix");
415 }
416 if (!IsHead || !suffix.IsHead)
417 {
419 }
420 if (suffix.Count == 0)
421 {
422 return;
423 }
424 bool flag = Count == 0;
425 byte[] buffer = suffix._buffer;
426 uint length = suffix._length;
427 int previousLength = suffix.PreviousLength;
428 int length2 = suffix.Length;
429 suffix._buffer = _buffer;
430 suffix._length = FrozenLength;
431 _buffer = buffer;
432 _length = length;
433 PreviousLength += suffix.Length + previousLength;
434 suffix._previousLengthOrFrozenSuffixLengthDelta = previousLength + length2 - suffix.Length;
435 if (!flag)
436 {
438 BlobBuilder firstChunk2 = suffix.FirstChunk;
441 suffix._nextOrPrevious = ((firstChunk2 != suffix) ? firstChunk2 : ((firstChunk != this) ? firstChunk : suffix));
442 if (nextOrPrevious != this)
443 {
444 nextOrPrevious._nextOrPrevious = suffix;
445 }
446 if (blobBuilder != suffix)
447 {
448 blobBuilder._nextOrPrevious = ((firstChunk != this) ? firstChunk : suffix);
449 }
450 }
452 suffix.CheckInvariants();
453 }
454
455 private void AddLength(int value)
456 {
457 _length += (uint)value;
458 }
459
460 [MethodImpl(MethodImplOptions.NoInlining)]
461 private void Expand(int newLength)
462 {
463 if (!IsHead)
464 {
466 }
468 if (blobBuilder.ChunkCapacity < newLength)
469 {
470 throw new InvalidOperationException(System.SR.Format(System.SR.ReturnedBuilderSizeTooSmall, GetType(), "AllocateChunk"));
471 }
472 byte[] buffer = blobBuilder._buffer;
473 if (_length == 0)
474 {
475 blobBuilder._buffer = _buffer;
476 _buffer = buffer;
477 }
478 else
479 {
482 if (nextOrPrevious == this)
483 {
485 }
486 else
487 {
488 blobBuilder._nextOrPrevious = firstChunk;
489 nextOrPrevious._nextOrPrevious = blobBuilder;
491 }
492 blobBuilder._buffer = _buffer;
493 blobBuilder._length = FrozenLength;
494 blobBuilder._previousLengthOrFrozenSuffixLengthDelta = PreviousLength;
495 _buffer = buffer;
497 _length = 0u;
498 }
500 }
501
503 {
504 if (byteCount < 0)
505 {
506 Throw.ArgumentOutOfRange("byteCount");
507 }
509 return new Blob(_buffer, start, byteCount);
510 }
511
513 {
514 uint num = _length;
515 if (num > _buffer.Length - byteCount)
516 {
518 num = 0u;
519 }
520 _length = num + (uint)byteCount;
521 return (int)num;
522 }
523
525 {
527 }
528
529 public void WriteBytes(byte value, int byteCount)
530 {
531 if (byteCount < 0)
532 {
533 Throw.ArgumentOutOfRange("byteCount");
534 }
535 if (!IsHead)
536 {
538 }
539 int num = Math.Min(FreeBytes, byteCount);
540 _buffer.WriteBytes(Length, value, num);
541 AddLength(num);
542 int num2 = byteCount - num;
543 if (num2 > 0)
544 {
545 Expand(num2);
546 _buffer.WriteBytes(0, value, num2);
548 }
549 }
550
551 public unsafe void WriteBytes(byte* buffer, int byteCount)
552 {
553 if (buffer == null)
554 {
555 Throw.ArgumentNull("buffer");
556 }
557 if (byteCount < 0)
558 {
559 Throw.ArgumentOutOfRange("byteCount");
560 }
561 if (!IsHead)
562 {
564 }
566 }
567
568 private unsafe void WriteBytesUnchecked(byte* buffer, int byteCount)
569 {
570 int num = Math.Min(FreeBytes, byteCount);
572 AddLength(num);
573 int num2 = byteCount - num;
574 if (num2 > 0)
575 {
576 Expand(num2);
577 Marshal.Copy((IntPtr)(buffer + num), _buffer, 0, num2);
579 }
580 }
581
583 {
584 if (source == null)
585 {
586 throw new ArgumentNullException("source");
587 }
588 if (byteCount < 0)
589 {
590 throw new ArgumentOutOfRangeException("byteCount");
591 }
592 if (byteCount == 0)
593 {
594 return 0;
595 }
596 int num = 0;
598 if (num2 > 0)
599 {
600 num = source.TryReadAll(_buffer, Length, num2);
601 AddLength(num);
602 if (num != num2)
603 {
604 return num;
605 }
606 }
607 int num3 = byteCount - num2;
608 if (num3 > 0)
609 {
610 Expand(num3);
611 num = source.TryReadAll(_buffer, 0, num3);
612 AddLength(num);
613 num += num2;
614 }
615 return num;
616 }
617
619 {
620 WriteBytes(buffer, 0, (!buffer.IsDefault) ? buffer.Length : 0);
621 }
622
627
628 public void WriteBytes(byte[] buffer)
629 {
630 WriteBytes(buffer, 0, (buffer != null) ? buffer.Length : 0);
631 }
632
633 public unsafe void WriteBytes(byte[] buffer, int start, int byteCount)
634 {
635 if (buffer == null)
636 {
637 Throw.ArgumentNull("buffer");
638 }
639 BlobUtilities.ValidateRange(buffer.Length, start, byteCount, "byteCount");
640 if (!IsHead)
641 {
643 }
644 if (buffer.Length != 0)
645 {
646 fixed (byte* ptr = &buffer[0])
647 {
649 }
650 }
651 }
652
653 public void PadTo(int position)
654 {
655 WriteBytes(0, position - Count);
656 }
657
658 public void Align(int alignment)
659 {
660 int count = Count;
662 }
663
664 public void WriteBoolean(bool value)
665 {
666 WriteByte((byte)(value ? 1u : 0u));
667 }
668
669 public void WriteByte(byte value)
670 {
672 _buffer.WriteByte(start, value);
673 }
674
675 public void WriteSByte(sbyte value)
676 {
677 WriteByte((byte)value);
678 }
679
680 public void WriteDouble(double value)
681 {
683 _buffer.WriteDouble(start, value);
684 }
685
686 public void WriteSingle(float value)
687 {
689 _buffer.WriteSingle(start, value);
690 }
691
692 public void WriteInt16(short value)
693 {
694 WriteUInt16((ushort)value);
695 }
696
697 public void WriteUInt16(ushort value)
698 {
700 _buffer.WriteUInt16(start, value);
701 }
702
703 public void WriteInt16BE(short value)
704 {
705 WriteUInt16BE((ushort)value);
706 }
707
708 public void WriteUInt16BE(ushort value)
709 {
711 _buffer.WriteUInt16BE(start, value);
712 }
713
714 public void WriteInt32BE(int value)
715 {
716 WriteUInt32BE((uint)value);
717 }
718
719 public void WriteUInt32BE(uint value)
720 {
722 _buffer.WriteUInt32BE(start, value);
723 }
724
725 public void WriteInt32(int value)
726 {
727 WriteUInt32((uint)value);
728 }
729
730 public void WriteUInt32(uint value)
731 {
733 _buffer.WriteUInt32(start, value);
734 }
735
736 public void WriteInt64(long value)
737 {
738 WriteUInt64((ulong)value);
739 }
740
741 public void WriteUInt64(ulong value)
742 {
744 _buffer.WriteUInt64(start, value);
745 }
746
747 public void WriteDecimal(decimal value)
748 {
750 _buffer.WriteDecimal(start, value);
751 }
752
753 public void WriteGuid(Guid value)
754 {
756 _buffer.WriteGuid(start, value);
757 }
758
760 {
761 WriteInt64(value.Ticks);
762 }
763
764 public void WriteReference(int reference, bool isSmall)
765 {
766 if (isSmall)
767 {
768 WriteUInt16((ushort)reference);
769 }
770 else
771 {
773 }
774 }
775
776 public unsafe void WriteUTF16(char[] value)
777 {
778 if (value == null)
779 {
780 Throw.ArgumentNull("value");
781 }
782 if (!IsHead)
783 {
785 }
786 if (value.Length == 0)
787 {
788 return;
789 }
791 {
792 fixed (char* buffer = &value[0])
793 {
794 WriteBytesUnchecked((byte*)buffer, value.Length * 2);
795 }
796 return;
797 }
798 for (int i = 0; i < value.Length; i++)
799 {
800 WriteUInt16(value[i]);
801 }
802 }
803
804 public unsafe void WriteUTF16(string value)
805 {
806 if (value == null)
807 {
808 Throw.ArgumentNull("value");
809 }
810 if (!IsHead)
811 {
813 }
815 {
816 fixed (char* buffer = value)
817 {
818 WriteBytesUnchecked((byte*)buffer, value.Length * 2);
819 }
820 return;
821 }
822 for (int i = 0; i < value.Length; i++)
823 {
824 WriteUInt16(value[i]);
825 }
826 }
827
828 public void WriteSerializedString(string? value)
829 {
830 if (value == null)
831 {
832 WriteByte(byte.MaxValue);
833 }
834 else
835 {
836 WriteUTF8(value, 0, value.Length, allowUnpairedSurrogates: true, prependSize: true);
837 }
838 }
839
840 public void WriteUserString(string value)
841 {
842 if (value == null)
843 {
844 throw new ArgumentNullException("value");
845 }
849 }
850
851 public void WriteUTF8(string value, bool allowUnpairedSurrogates = true)
852 {
853 if (value == null)
854 {
855 Throw.ArgumentNull("value");
856 }
858 }
859
860 internal unsafe void WriteUTF8(string str, int start, int length, bool allowUnpairedSurrogates, bool prependSize)
861 {
862 if (!IsHead)
863 {
865 }
866 fixed (char* ptr = str)
867 {
868 char* ptr2 = ptr + start;
869 int byteLimit = FreeBytes - (prependSize ? 4 : 0);
870 char* remainder;
872 int num = (int)(remainder - ptr2);
873 int charCount = length - num;
875 if (prependSize)
876 {
878 }
881 if (uTF8ByteCount2 > 0)
882 {
886 }
887 }
888 }
889
894
896 {
898 }
899
900 public void WriteConstant(object? value)
901 {
903 }
904
905 internal string GetDebuggerDisplay()
906 {
907 if (!IsHead)
908 {
909 return "<" + Display(_buffer, Length) + ">";
910 }
911 return string.Join("->", from chunk in GetChunks()
912 select "[" + Display(chunk._buffer, chunk.Length) + "]");
913 }
914
915 private static string Display(byte[] bytes, int length)
916 {
917 if (length > 64)
918 {
919 return BitConverter.ToString(bytes, 0, 32) + "-...-" + BitConverter.ToString(bytes, length - 32, 32);
920 }
921 return BitConverter.ToString(bytes, 0, length);
922 }
923}
static unsafe void Copy(Array sourceArray, Array destinationArray, int length)
Definition Array.cs:624
static string ToString(byte[] value, int startIndex, int length)
static readonly bool IsLittleEndian
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static byte Max(byte val1, byte val2)
Definition Math.cs:738
static void ValidateRange(int bufferLength, int start, int byteCount, string byteCountParameterName)
static byte GetUserStringTrailingByte(string str)
static unsafe int GetUTF8ByteCount(string str)
static int GetUserStringByteLength(int characterCount)
static uint Align(uint position, uint alignment)
static bool Equals(ImmutableArray< byte > x, ImmutableArray< byte > y)
static ? byte[] DangerousGetUnderlyingArray(ImmutableArray< byte > array)
static ImmutableArray< byte > DangerousCreateFromUnderlyingArray(ref byte[]? array)
void WriteBytes(ImmutableArray< byte > buffer)
unsafe void WriteUTF8(string str, int start, int length, bool allowUnpairedSurrogates, bool prependSize)
ImmutableArray< byte > ToImmutableArray()
int TryWriteBytes(Stream source, int byteCount)
unsafe void WriteUTF16(char[] value)
unsafe void WriteUTF16(string value)
void WriteSerializedString(string? value)
void WriteContentTo(Stream destination)
void LinkPrefix(BlobBuilder prefix)
void LinkSuffix(BlobBuilder suffix)
unsafe void WriteBytesUnchecked(byte *buffer, int byteCount)
void WriteUTF8(string value, bool allowUnpairedSurrogates=true)
void WriteContentTo(BlobBuilder destination)
void WriteContentTo(ref BlobWriter destination)
void WriteBytes(ImmutableArray< byte > buffer, int start, int byteCount)
unsafe void WriteBytes(byte *buffer, int byteCount)
byte[] ToArray(int start, int byteCount)
virtual BlobBuilder AllocateChunk(int minimalSize)
static string Display(byte[] bytes, int length)
ImmutableArray< byte > ToImmutableArray(int start, int byteCount)
void WriteReference(int reference, bool isSmall)
bool ContentEquals(BlobBuilder other)
unsafe void WriteBytes(byte[] buffer, int start, int byteCount)
void WriteBytes(byte value, int byteCount)
static void WriteCompressedSignedInteger(ref BlobWriter writer, int value)
static void WriteCompressedInteger(ref BlobWriter writer, uint value)
static void WriteConstant(ref BlobWriter writer, object? value)
static void ArgumentNull(string parameterName)
Definition Throw.cs:110
static void InvalidOperationBuilderAlreadyLinked()
Definition Throw.cs:61
static void ArgumentOutOfRange(string parameterName)
Definition Throw.cs:145
static void Copy(int[] source, int startIndex, IntPtr destination, int length)
Definition Marshal.cs:800
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string ReturnedBuilderSizeTooSmall
Definition SR.cs:184
Definition SR.cs:7
new IEnumerator< T > GetEnumerator()