public static string UnescapeDataString(string stringToUnescape) { if ((object)stringToUnescape == null) { throw new ArgumentNullException(nameof(stringToUnescape)); } if (stringToUnescape.Length == 0) { return(string.Empty); } unsafe { fixed(char *pStr = stringToUnescape) { int position; for (position = 0; position < stringToUnescape.Length; ++position) { if (pStr[position] == '%') { break; } } if (position == stringToUnescape.Length) { return(stringToUnescape); } UnescapeMode unescapeMode = UnescapeMode.Unescape | UnescapeMode.UnescapeAll; position = 0; ValueStringBuilder vsb = new ValueStringBuilder(stringToUnescape.Length); UriHelper.UnescapeString(stringToUnescape, 0, stringToUnescape.Length, ref vsb, ref position, c_DummyChar, c_DummyChar, c_DummyChar, unescapeMode, null, false); ReadOnlySpan <char> resultSpan = vsb.AsSpan(0, position); string result = resultSpan.SequenceEqual(stringToUnescape) ? stringToUnescape : resultSpan.ToString(); vsb.Dispose(); return(result); } } }
public static string UnescapeDataString(string stringToUnescape) { if ((object)stringToUnescape == null) { throw new ArgumentNullException("stringToUnescape"); } if (stringToUnescape.Length == 0) { return(string.Empty); } unsafe { fixed(char *pStr = stringToUnescape) { int position; for (position = 0; position < stringToUnescape.Length; ++position) { if (pStr[position] == '%') { break; } } if (position == stringToUnescape.Length) { return(stringToUnescape); } UnescapeMode unescapeMode = UnescapeMode.Unescape | UnescapeMode.UnescapeAll; position = 0; char[] dest = new char[stringToUnescape.Length]; dest = UriHelper.UnescapeString(stringToUnescape, 0, stringToUnescape.Length, dest, ref position, c_DummyChar, c_DummyChar, c_DummyChar, unescapeMode, null, false); return(new string(dest, 0, position)); } } }
internal unsafe static char[] UnescapeString(char* pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) { byte [] bytes = null; byte escapedReallocations = 0; bool escapeReserved = false; int next = start; bool iriParsing = Uri.IriParsingStatic(syntax) && ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.EscapeUnescape); while (true) { // we may need to re-pin dest[] fixed (char* pDest = dest) { if ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.CopyOnly) { while (start < end) pDest[destPosition++] = pStr[start++]; return dest; } while (true) { char ch = (char)0; for (;next < end; ++next) { if ((ch = pStr[next]) == '%') { if ((unescapeMode & UnescapeMode.Unescape) == 0) { // re-escape, don't check anything else escapeReserved = true; } else if (next+2 < end) { ch = EscapedAscii(pStr[next+1], pStr[next+2]); // Unescape a good sequence if full unescape is requested if (unescapeMode >= UnescapeMode.UnescapeAll) { if (ch == Uri.c_DummyChar) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { // Should be a rare case where the app tries to feed an invalid escaped sequence throw new UriFormatException(SR.GetString(SR.net_uri_BadString)); } continue; } } // re-escape % from an invalid sequence else if (ch == Uri.c_DummyChar) { if ((unescapeMode & UnescapeMode.Escape) != 0) escapeReserved = true; else continue; // we should throw instead but since v1.0 woudl just print '%' } // Do not unescape '%' itself unless full unescape is requested else if (ch == '%') { next += 2; continue; } // Do not unescape a reserved char unless full unescape is requested else if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3) { next += 2; continue; } // Do not unescape a dangerous char unless it's V1ToStringFlags mode else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && IsNotSafeForUnescape(ch)) { next += 2; continue; } else if (iriParsing && ((ch <='\x9F' && IsNotSafeForUnescape(ch)) || (ch >'\x9F' &&!Uri.CheckIriUnicodeRange(ch, isQuery)))) { // check if unenscaping gives a char ouside iri range // if it does then keep it escaped next += 2; continue; } // unescape escaped char or escape % break; } else if (unescapeMode >= UnescapeMode.UnescapeAll) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { // Should be a rare case where the app tries to feed an invalid escaped sequence throw new UriFormatException(SR.GetString(SR.net_uri_BadString)); } // keep a '%' as part of a bogus sequence continue; } else { escapeReserved = true; } // escape (escapeReserved==ture) or otheriwse unescape the sequence break; } else if ((unescapeMode & (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) == (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) { continue; } else if ((unescapeMode & UnescapeMode.Escape) != 0) { // Could actually escape some of the characters if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3) { // found an unescaped reserved character -> escape it escapeReserved = true; break; } else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && (ch <= '\x1F' || (ch >= '\x7F' && ch <= '\x9F'))) { // found an unescaped reserved character -> escape it escapeReserved = true; break; } } } //copy off previous characters from input while (start < next) pDest[destPosition++] = pStr[start++]; if (next != end) { //VsWhidbey#87423 if (escapeReserved) { //escape that char // Since this should be _really_ rare case, reallocate with constant size increase of 30 rsvd-type characters. if (escapedReallocations == 0) { escapedReallocations = 30; char[] newDest = new char[dest.Length + escapedReallocations*3]; fixed (char *pNewDest = newDest) { for (int i = 0; i < destPosition; ++i) pNewDest[i] = pDest[i]; } dest = newDest; // re-pin new dest[] array goto dest_fixed_loop_break; } else { --escapedReallocations; EscapeAsciiChar(pStr[next], dest, ref destPosition); escapeReserved = false; start = ++next; continue; } } // unescaping either one Ascii or possibly multiple Unicode if (ch <= '\x7F') { //ASCII dest[destPosition++] = ch; next+=3; start = next; continue; } // Unicode int byteCount = 1; // lazy initialization of max size, will reuse the array for next sequences if ((object) bytes == null) bytes = new byte[end - next]; bytes[0] = (byte)ch; next+=3; while (next < end) { // Check on exit criterion if ((ch = pStr[next]) != '%' || next+2 >= end) break; // already made sure we have 3 characters in str ch = EscapedAscii(pStr[next+1], pStr[next+2]); //invalid hex sequence ? if (ch == Uri.c_DummyChar) break; // character is not part of a UTF-8 sequence ? else if (ch < '\x80') break; else { //a UTF-8 sequence bytes[byteCount++] = (byte)ch; next += 3; } } Encoding noFallbackCharUTF8 = (Encoding)Encoding.UTF8.Clone(); noFallbackCharUTF8.EncoderFallback = new EncoderReplacementFallback(""); noFallbackCharUTF8.DecoderFallback = new DecoderReplacementFallback(""); char[] unescapedChars = new char[bytes.Length]; int charCount = noFallbackCharUTF8.GetChars(bytes, 0, byteCount, unescapedChars, 0); start = next; // match exact bytes // Do not unescape chars not allowed by Iri // need to check for invalid utf sequences that may not have given any chars MatchUTF8Sequence(pDest, dest, ref destPosition, unescapedChars, charCount, bytes, byteCount, isQuery, iriParsing); } if (next == end) goto done; } dest_fixed_loop_break: ; } } done: return dest; }
// // This method will assume that any good Escaped Sequence will be unescaped in the output // - Assumes Dest.Length - detPosition >= end-start // - UnescapeLevel controls various modes of opearion // - Any "bad" escape sequence will remain as is or '%' will be escaped. // - destPosition tells the starting index in dest for placing the result. // On return destPosition tells the last character + 1 postion in the "dest" array. // - The control chars and chars passed in rsdvX parameters may be re-escaped depending on UnescapeLevel // - It is a RARE case when Unescape actually needs escaping some characteres mentioned above. // For this reason it returns a char[] that is usually the same ref as the input "dest" value. // internal unsafe static char[] UnescapeString(string input, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) { fixed (char *pStr = input) { return UnescapeString(pStr, start, end, dest, ref destPosition, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery); } }
internal unsafe static char[] UnescapeString(char *pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) { byte [] bytes = null; byte escapedReallocations = 0; bool escapeReserved = false; int next = start; bool iriParsing = Uri.IriParsingStatic(syntax) && ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.EscapeUnescape); while (true) { // we may need to re-pin dest[] fixed(char *pDest = dest) { if ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.CopyOnly) { while (start < end) { pDest[destPosition++] = pStr[start++]; } return(dest); } while (true) { char ch = (char)0; for (; next < end; ++next) { if ((ch = pStr[next]) == '%') { if ((unescapeMode & UnescapeMode.Unescape) == 0) { // re-escape, don't check anything else escapeReserved = true; } else if (next + 2 < end) { ch = EscapedAscii(pStr[next + 1], pStr[next + 2]); // Unescape a good sequence if full unescape is requested if (unescapeMode >= UnescapeMode.UnescapeAll) { if (ch == Uri.c_DummyChar) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { // Should be a rare case where the app tries to feed an invalid escaped sequence throw new UriFormatException(SR.GetString(SR.net_uri_BadString)); } continue; } } // re-escape % from an invalid sequence else if (ch == Uri.c_DummyChar) { if ((unescapeMode & UnescapeMode.Escape) != 0) { escapeReserved = true; } else { continue; // we should throw instead but since v1.0 woudl just print '%' } } // Do not unescape '%' itself unless full unescape is requested else if (ch == '%') { next += 2; continue; } // Do not unescape a reserved char unless full unescape is requested else if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3) { next += 2; continue; } // Do not unescape a dangerous char unless it's V1ToStringFlags mode else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && IsNotSafeForUnescape(ch)) { next += 2; continue; } else if (iriParsing && ((ch <= '\x9F' && IsNotSafeForUnescape(ch)) || (ch > '\x9F' && !IriHelper.CheckIriUnicodeRange(ch, isQuery)))) { // check if unenscaping gives a char ouside iri range // if it does then keep it escaped next += 2; continue; } // unescape escaped char or escape % break; } else if (unescapeMode >= UnescapeMode.UnescapeAll) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { // Should be a rare case where the app tries to feed an invalid escaped sequence throw new UriFormatException(SR.GetString(SR.net_uri_BadString)); } // keep a '%' as part of a bogus sequence continue; } else { escapeReserved = true; } // escape (escapeReserved==ture) or otheriwse unescape the sequence break; } else if ((unescapeMode & (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) == (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) { continue; } else if ((unescapeMode & UnescapeMode.Escape) != 0) { // Could actually escape some of the characters if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3) { // found an unescaped reserved character -> escape it escapeReserved = true; break; } else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && (ch <= '\x1F' || (ch >= '\x7F' && ch <= '\x9F'))) { // found an unescaped reserved character -> escape it escapeReserved = true; break; } } } //copy off previous characters from input while (start < next) { pDest[destPosition++] = pStr[start++]; } if (next != end) { //VsWhidbey#87423 if (escapeReserved) { //escape that char // Since this should be _really_ rare case, reallocate with constant size increase of 30 rsvd-type characters. if (escapedReallocations == 0) { escapedReallocations = 30; char[] newDest = new char[dest.Length + escapedReallocations * 3]; fixed(char *pNewDest = newDest) { for (int i = 0; i < destPosition; ++i) { pNewDest[i] = pDest[i]; } } dest = newDest; // re-pin new dest[] array goto dest_fixed_loop_break; } else { --escapedReallocations; EscapeAsciiChar(pStr[next], dest, ref destPosition); escapeReserved = false; start = ++next; continue; } } // unescaping either one Ascii or possibly multiple Unicode if (ch <= '\x7F') { //ASCII dest[destPosition++] = ch; next += 3; start = next; continue; } // Unicode int byteCount = 1; // lazy initialization of max size, will reuse the array for next sequences if ((object)bytes == null) { bytes = new byte[end - next]; } bytes[0] = (byte)ch; next += 3; while (next < end) { // Check on exit criterion if ((ch = pStr[next]) != '%' || next + 2 >= end) { break; } // already made sure we have 3 characters in str ch = EscapedAscii(pStr[next + 1], pStr[next + 2]); //invalid hex sequence ? if (ch == Uri.c_DummyChar) { break; } // character is not part of a UTF-8 sequence ? else if (ch < '\x80') { break; } else { //a UTF-8 sequence bytes[byteCount++] = (byte)ch; next += 3; } } Encoding noFallbackCharUTF8 = (Encoding)Encoding.UTF8.Clone(); noFallbackCharUTF8.EncoderFallback = new EncoderReplacementFallback(""); noFallbackCharUTF8.DecoderFallback = new DecoderReplacementFallback(""); char[] unescapedChars = new char[bytes.Length]; int charCount = noFallbackCharUTF8.GetChars(bytes, 0, byteCount, unescapedChars, 0); start = next; // match exact bytes // Do not unescape chars not allowed by Iri // need to check for invalid utf sequences that may not have given any chars MatchUTF8Sequence(pDest, dest, ref destPosition, unescapedChars, charCount, bytes, byteCount, isQuery, iriParsing); } if (next == end) { goto done; } } dest_fixed_loop_break :; } } done : return(dest); }
// // This method will assume that any good Escaped Sequence will be unescaped in the output // - Assumes Dest.Length - detPosition >= end-start // - UnescapeLevel controls various modes of opearion // - Any "bad" escape sequence will remain as is or '%' will be escaped. // - destPosition tells the starting index in dest for placing the result. // On return destPosition tells the last character + 1 postion in the "dest" array. // - The control chars and chars passed in rsdvX parameters may be re-escaped depending on UnescapeLevel // - It is a RARE case when Unescape actually needs escaping some characteres mentioned above. // For this reason it returns a char[] that is usually the same ref as the input "dest" value. // internal unsafe static char[] UnescapeString(string input, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) { fixed(char *pStr = input) { return(UnescapeString(pStr, start, end, dest, ref destPosition, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery)); } }
private static unsafe char[] UnescapeString(char* pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery, bool readOnlyConfig) { byte[] bytes = null; byte num = 0; bool flag = false; int index = start; bool iriParsing = (s_IriParsing && (readOnlyConfig || (!readOnlyConfig && IriParsingStatic(syntax)))) && ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.EscapeUnescape); Label_002E:; try { fixed (char* chRef = dest) { char ch; if ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.CopyOnly) { while (start < end) { chRef[destPosition++] = pStr[start++]; } return dest; } Label_007F: ch = '\0'; while (index < end) { ch = pStr[index]; if (ch == '%') { if ((unescapeMode & UnescapeMode.Unescape) == UnescapeMode.CopyOnly) { flag = true; } else { if ((index + 2) < end) { ch = EscapedAscii(pStr[index + 1], pStr[index + 2]); if (unescapeMode >= UnescapeMode.UnescapeAll) { if (ch == 0xffff) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { throw new UriFormatException(System.SR.GetString("net_uri_BadString")); } goto Label_01E8; } break; } if (ch == 0xffff) { if ((unescapeMode & UnescapeMode.Escape) == UnescapeMode.CopyOnly) { goto Label_01E8; } flag = true; break; } if (ch == '%') { index += 2; } else if (((ch == rsvd1) || (ch == rsvd2)) || (ch == rsvd3)) { index += 2; } else if (((unescapeMode & UnescapeMode.V1ToStringFlag) == UnescapeMode.CopyOnly) && IsNotSafeForUnescape(ch)) { index += 2; } else { if (!iriParsing || (((ch > '\x009f') || !IsNotSafeForUnescape(ch)) && ((ch <= '\x009f') || CheckIriUnicodeRange(ch, isQuery)))) { break; } index += 2; } goto Label_01E8; } if (unescapeMode >= UnescapeMode.UnescapeAll) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { throw new UriFormatException(System.SR.GetString("net_uri_BadString")); } goto Label_01E8; } flag = true; } break; } if (((unescapeMode & (UnescapeMode.UnescapeAll | UnescapeMode.Unescape)) != (UnescapeMode.UnescapeAll | UnescapeMode.Unescape)) && ((unescapeMode & UnescapeMode.Escape) != UnescapeMode.CopyOnly)) { if (((ch == rsvd1) || (ch == rsvd2)) || (ch == rsvd3)) { flag = true; break; } if (((unescapeMode & UnescapeMode.V1ToStringFlag) == UnescapeMode.CopyOnly) && ((ch <= '\x001f') || ((ch >= '\x007f') && (ch <= '\x009f')))) { flag = true; break; } } Label_01E8: index++; } while (start < index) { chRef[destPosition++] = pStr[start++]; } if (index != end) { if (flag) { if (num == 0) { num = 30; char[] chArray = new char[dest.Length + (num * 3)]; fixed (char* chRef2 = chArray) { for (int i = 0; i < destPosition; i++) { chRef2[i] = chRef[i]; } } dest = chArray; goto Label_002E; } num = (byte) (num - 1); EscapeAsciiChar(pStr[index], dest, ref destPosition); flag = false; start = ++index; goto Label_007F; } if (ch <= '\x007f') { dest[destPosition++] = ch; index += 3; start = index; goto Label_007F; } int byteCount = 1; if (bytes == null) { bytes = new byte[end - index]; } bytes[0] = (byte) ch; index += 3; while (index < end) { if (((ch = pStr[index]) != '%') || ((index + 2) >= end)) { break; } ch = EscapedAscii(pStr[index + 1], pStr[index + 2]); if ((ch == 0xffff) || (ch < '\x0080')) { break; } bytes[byteCount++] = (byte) ch; index += 3; } Encoding encoding = Encoding.GetEncoding("utf-8", new EncoderReplacementFallback(""), new DecoderReplacementFallback("")); char[] chars = new char[bytes.Length]; int charCount = encoding.GetChars(bytes, 0, byteCount, chars, 0); if (charCount != 0) { start = index; MatchUTF8Sequence(chRef, dest, ref destPosition, chars, charCount, bytes, isQuery, iriParsing); } else { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { throw new UriFormatException(System.SR.GetString("net_uri_BadString")); } index = start + 3; start = index; dest[destPosition++] = (char) bytes[0]; } } if (index != end) { goto Label_007F; } return dest; } } finally { chRef = null; } return dest; }
private static unsafe char[] UnescapeString(string input, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery, bool readOnlyConfig) { fixed (char* str = ((char*) input)) { char* pStr = str; return UnescapeString(pStr, start, end, dest, ref destPosition, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery, readOnlyConfig); } }
internal static unsafe void UnescapeString(char *pStr, int start, int end, ref ValueStringBuilder dest, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser?syntax, bool isQuery) { if ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.CopyOnly) { dest.Append(pStr + start, end - start); return; } bool escapeReserved = false; bool iriParsing = Uri.IriParsingStatic(syntax) && ((unescapeMode & UnescapeMode.EscapeUnescape) == UnescapeMode.EscapeUnescape); for (int next = start; next < end;) { char ch = (char)0; for (; next < end; ++next) { if ((ch = pStr[next]) == '%') { if ((unescapeMode & UnescapeMode.Unescape) == 0) { // re-escape, don't check anything else escapeReserved = true; } else if (next + 2 < end) { ch = DecodeHexChars(pStr[next + 1], pStr[next + 2]); // Unescape a good sequence if full unescape is requested if (unescapeMode >= UnescapeMode.UnescapeAll) { if (ch == Uri.c_DummyChar) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { // Should be a rare case where the app tries to feed an invalid escaped sequence throw new UriFormatException(SR.net_uri_BadString); } continue; } } // re-escape % from an invalid sequence else if (ch == Uri.c_DummyChar) { if ((unescapeMode & UnescapeMode.Escape) != 0) { escapeReserved = true; } else { continue; // we should throw instead but since v1.0 would just print '%' } } // Do not unescape '%' itself unless full unescape is requested else if (ch == '%') { next += 2; continue; } // Do not unescape a reserved char unless full unescape is requested else if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3) { next += 2; continue; } // Do not unescape a dangerous char unless it's V1ToStringFlags mode else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && IsNotSafeForUnescape(ch)) { next += 2; continue; } else if (iriParsing && ((ch <= '\x9F' && IsNotSafeForUnescape(ch)) || (ch > '\x9F' && !IriHelper.CheckIriUnicodeRange(ch, isQuery)))) { // check if unenscaping gives a char outside iri range // if it does then keep it escaped next += 2; continue; } // unescape escaped char or escape % break; } else if (unescapeMode >= UnescapeMode.UnescapeAll) { if (unescapeMode >= UnescapeMode.UnescapeAllOrThrow) { // Should be a rare case where the app tries to feed an invalid escaped sequence throw new UriFormatException(SR.net_uri_BadString); } // keep a '%' as part of a bogus sequence continue; } else { escapeReserved = true; } // escape (escapeReserved==true) or otherwise unescape the sequence break; } else if ((unescapeMode & (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) == (UnescapeMode.Unescape | UnescapeMode.UnescapeAll)) { continue; } else if ((unescapeMode & UnescapeMode.Escape) != 0) { // Could actually escape some of the characters if (ch == rsvd1 || ch == rsvd2 || ch == rsvd3) { // found an unescaped reserved character -> escape it escapeReserved = true; break; } else if ((unescapeMode & UnescapeMode.V1ToStringFlag) == 0 && (ch <= '\x1F' || (ch >= '\x7F' && ch <= '\x9F'))) { // found an unescaped reserved character -> escape it escapeReserved = true; break; } } } //copy off previous characters from input while (start < next) { dest.Append(pStr[start++]); } if (next != end) { if (escapeReserved) { EscapeAsciiChar((byte)pStr[next], ref dest); escapeReserved = false; next++; } else if (ch <= 127) { dest.Append(ch); next += 3; } else { // Unicode int charactersRead = PercentEncodingHelper.UnescapePercentEncodedUTF8Sequence( pStr + next, end - next, ref dest, isQuery, iriParsing); Debug.Assert(charactersRead > 0); next += charactersRead; } start = next; } } }
internal static unsafe void UnescapeString(ReadOnlySpan <char> input, ref ValueStringBuilder dest, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser?syntax, bool isQuery) { fixed(char *pStr = &MemoryMarshal.GetReference(input)) { UnescapeString(pStr, 0, input.Length, ref dest, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery); } }
// // This method will assume that any good Escaped Sequence will be unescaped in the output // - Assumes Dest.Length - detPosition >= end-start // - UnescapeLevel controls various modes of operation // - Any "bad" escape sequence will remain as is or '%' will be escaped. // - destPosition tells the starting index in dest for placing the result. // On return destPosition tells the last character + 1 position in the "dest" array. // - The control chars and chars passed in rsdvX parameters may be re-escaped depending on UnescapeLevel // - It is a RARE case when Unescape actually needs escaping some characters mentioned above. // For this reason it returns a char[] that is usually the same ref as the input "dest" value. // internal static unsafe void UnescapeString(string input, int start, int end, ref ValueStringBuilder dest, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser?syntax, bool isQuery) { fixed(char *pStr = input) { UnescapeString(pStr, start, end, ref dest, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery); } }
internal static unsafe char[] UnescapeString(char *pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser?syntax, bool isQuery) { ValueStringBuilder vsb = new ValueStringBuilder(dest.Length); vsb.Append(dest.AsSpan(0, destPosition)); UnescapeString(pStr, start, end, ref vsb, rsvd1, rsvd2, rsvd3, unescapeMode, syntax, isQuery); if (vsb.Length > dest.Length) { dest = vsb.AsSpan().ToArray(); } else { vsb.AsSpan(destPosition).TryCopyTo(dest.AsSpan(destPosition)); } destPosition = vsb.Length; vsb.Dispose(); return(dest); }
internal static char[] UnescapeString(string input, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) => default; // 0x00000001809CB150-0x00000001809CB230 internal static unsafe char[] UnescapeString(char *pStr, int start, int end, char[] dest, ref int destPosition, char rsvd1, char rsvd2, char rsvd3, UnescapeMode unescapeMode, UriParser syntax, bool isQuery) => default; // 0x00000001809CB230-0x00000001809CBC20