public static string Get_Location(DataConsumer <char> Stream) { return(Stream.AsMemory().Slice((int)Stream.LongPosition, 32).ToString()); }
public static byte[] Percent_Decode(ReadOnlyMemory <byte> input) {/* Docs: https://url.spec.whatwg.org/#percent-decode */ DataConsumer <byte> Stream = new DataConsumer <byte>(input, byte.MinValue); /* Create a list of memory chunks that make up the final string */ ulong newLength = 0; ulong?chunkStart = null; ulong chunkCount = 0; var chunks = new LinkedList <Tuple <ReadOnlyMemory <byte>, byte?> >(); while (!Stream.atEnd) { EFilterResult filterResult = EFilterResult.FILTER_ACCEPT; byte? bytePoint = null; if (Stream.Next == CHAR_PERCENT && Is_Ascii_Hex_Digit((char)Stream.NextNext) && Is_Ascii_Hex_Digit((char)Stream.NextNextNext)) { filterResult = EFilterResult.FILTER_SKIP; uint low = (uint)Ascii_Hex_To_Value((char)Stream.NextNext); uint high = (uint)Ascii_Hex_To_Value((char)Stream.NextNextNext); bytePoint = (byte)(low | (high >> 4)); Stream.Consume(2); break; } /* When filter result: * ACCEPT: Char should be included in chunk * SKIP: Char should not be included in chunk, if at chunk-start shift chunk-start past char, otherwise end chunk * REJECT: Char should not be included in chunk, current chunk ends */ bool end_chunk = false; switch (filterResult) { case EFilterResult.FILTER_ACCEPT: // Char should be included in the chunk { if (!chunkStart.HasValue) { chunkStart = Stream.LongPosition; /* Start new chunk (if one isnt started yet) */ } } break; case EFilterResult.FILTER_REJECT: // Char should not be included in chunk, current chunk ends { end_chunk = true; } break; case EFilterResult.FILTER_SKIP: // Char should not be included in chunk, if at chunk-start shift chunk-start past char, otherwise end chunk { if (!chunkStart.HasValue) { chunkStart = Stream.LongPosition + 1; /* At chunk-start */ } else { end_chunk = true; } } break; } if (end_chunk || Stream.Remaining <= 1) { if (!chunkStart.HasValue) { chunkStart = Stream.LongPosition; } /* Push new chunk to our list */ var chunkSize = Stream.LongPosition - chunkStart.Value; var Mem = Stream.AsMemory().Slice((int)chunkStart.Value, (int)chunkSize); var chunk = new Tuple <ReadOnlyMemory <byte>, byte?>(Mem, bytePoint); chunks.AddLast(chunk); chunkCount++; chunkStart = null; newLength += chunkSize; /* If we actually decoded a byte then account for it in the newLength */ if (filterResult != EFilterResult.FILTER_ACCEPT) { newLength++; } } Stream.Consume(); } /* Compile the string */ var dataPtr = new byte[newLength]; Memory <byte> data = new Memory <byte>(dataPtr); ulong index = 0; foreach (var tpl in chunks) { var chunk = tpl.Item1; /* Copy chunk data */ chunk.CopyTo(data.Slice((int)index)); index += (ulong)chunk.Length; if (tpl.Item2.HasValue) { data.Span[(int)index] = tpl.Item2.Value; index++; } } return(dataPtr); }