mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
382 lines
9.7 KiB
382 lines
9.7 KiB
#nullable enable |
|
// |
|
// UnicodeNewline.cs |
|
// |
|
// Author: |
|
// Mike Krüger <mkrueger@xamarin.com> |
|
// |
|
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com) |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining a copy |
|
// of this software and associated documentation files (the "Software"), to deal |
|
// in the Software without restriction, including without limitation the rights |
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
// copies of the Software, and to permit persons to whom the Software is |
|
// furnished to do so, subject to the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be included in |
|
// all copies or substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
// THE SOFTWARE. |
|
using System; |
|
|
|
namespace ICSharpCode.Decompiler.Util |
|
{ |
|
public enum UnicodeNewline |
|
{ |
|
Unknown, |
|
|
|
/// <summary> |
|
/// Line Feed, U+000A |
|
/// </summary> |
|
LF = 0x0A, |
|
|
|
|
|
CRLF = 0x0D0A, |
|
|
|
/// <summary> |
|
/// Carriage Return, U+000D |
|
/// </summary> |
|
CR = 0x0D, |
|
|
|
/// <summary> |
|
/// Next Line, U+0085 |
|
/// </summary> |
|
NEL = 0x85, |
|
|
|
/// <summary> |
|
/// Vertical Tab, U+000B |
|
/// </summary> |
|
VT = 0x0B, |
|
|
|
/// <summary> |
|
/// Form Feed, U+000C |
|
/// </summary> |
|
FF = 0x0C, |
|
|
|
/// <summary> |
|
/// Line Separator, U+2028 |
|
/// </summary> |
|
LS = 0x2028, |
|
|
|
/// <summary> |
|
/// Paragraph Separator, U+2029 |
|
/// </summary> |
|
PS = 0x2029 |
|
} |
|
|
|
|
|
/// <summary> |
|
/// Defines unicode new lines according to Unicode Technical Report #13 |
|
/// http://www.unicode.org/standard/reports/tr13/tr13-5.html |
|
/// </summary> |
|
public static class NewLine |
|
{ |
|
/// <summary> |
|
/// Carriage Return, U+000D |
|
/// </summary> |
|
public const char CR = (char)0x0D; |
|
|
|
/// <summary> |
|
/// Line Feed, U+000A |
|
/// </summary> |
|
public const char LF = (char)0x0A; |
|
|
|
/// <summary> |
|
/// Next Line, U+0085 |
|
/// </summary> |
|
public const char NEL = (char)0x85; |
|
|
|
/// <summary> |
|
/// Vertical Tab, U+000B |
|
/// </summary> |
|
public const char VT = (char)0x0B; |
|
|
|
/// <summary> |
|
/// Form Feed, U+000C |
|
/// </summary> |
|
public const char FF = (char)0x0C; |
|
|
|
/// <summary> |
|
/// Line Separator, U+2028 |
|
/// </summary> |
|
public const char LS = (char)0x2028; |
|
|
|
/// <summary> |
|
/// Paragraph Separator, U+2029 |
|
/// </summary> |
|
public const char PS = (char)0x2029; |
|
|
|
/// <summary> |
|
/// Determines if a char is a new line delimiter. |
|
/// </summary> |
|
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns> |
|
/// <param name="curChar">The current character.</param> |
|
/// <param name="nextChar">A callback getting the next character (may be null).</param> |
|
public static int GetDelimiterLength(char curChar, Func<char>? nextChar = null) |
|
{ |
|
if (curChar == CR) |
|
{ |
|
if (nextChar != null && nextChar() == LF) |
|
return 2; |
|
return 1; |
|
} |
|
|
|
if (curChar == LF || curChar == NEL || curChar == VT || curChar == FF || curChar == LS || curChar == PS) |
|
return 1; |
|
return 0; |
|
} |
|
|
|
/// <summary> |
|
/// Determines if a char is a new line delimiter. |
|
/// </summary> |
|
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns> |
|
/// <param name="curChar">The current character.</param> |
|
/// <param name="nextChar">The next character (if != LF then length will always be 0 or 1).</param> |
|
public static int GetDelimiterLength(char curChar, char nextChar) |
|
{ |
|
if (curChar == CR) |
|
{ |
|
if (nextChar == LF) |
|
return 2; |
|
return 1; |
|
} |
|
|
|
if (curChar == LF || curChar == NEL || curChar == VT || curChar == FF || curChar == LS || curChar == PS) |
|
return 1; |
|
return 0; |
|
} |
|
|
|
|
|
/// <summary> |
|
/// Determines if a char is a new line delimiter. |
|
/// </summary> |
|
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns> |
|
/// <param name="curChar">The current character.</param> |
|
/// <param name = "length">The length of the delimiter</param> |
|
/// <param name = "type">The type of the delimiter</param> |
|
/// <param name="nextChar">A callback getting the next character (may be null).</param> |
|
public static bool TryGetDelimiterLengthAndType(char curChar, out int length, out UnicodeNewline type, Func<char>? nextChar = null) |
|
{ |
|
if (curChar == CR) |
|
{ |
|
if (nextChar != null && nextChar() == LF) |
|
{ |
|
length = 2; |
|
type = UnicodeNewline.CRLF; |
|
} |
|
else |
|
{ |
|
length = 1; |
|
type = UnicodeNewline.CR; |
|
|
|
} |
|
return true; |
|
} |
|
|
|
switch (curChar) |
|
{ |
|
case LF: |
|
type = UnicodeNewline.LF; |
|
length = 1; |
|
return true; |
|
case NEL: |
|
type = UnicodeNewline.NEL; |
|
length = 1; |
|
return true; |
|
case VT: |
|
type = UnicodeNewline.VT; |
|
length = 1; |
|
return true; |
|
case FF: |
|
type = UnicodeNewline.FF; |
|
length = 1; |
|
return true; |
|
case LS: |
|
type = UnicodeNewline.LS; |
|
length = 1; |
|
return true; |
|
case PS: |
|
type = UnicodeNewline.PS; |
|
length = 1; |
|
return true; |
|
} |
|
length = -1; |
|
type = UnicodeNewline.Unknown; |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// Determines if a char is a new line delimiter. |
|
/// </summary> |
|
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns> |
|
/// <param name="curChar">The current character.</param> |
|
/// <param name = "length">The length of the delimiter</param> |
|
/// <param name = "type">The type of the delimiter</param> |
|
/// <param name="nextChar">The next character (if != LF then length will always be 0 or 1).</param> |
|
public static bool TryGetDelimiterLengthAndType(char curChar, out int length, out UnicodeNewline type, char nextChar) |
|
{ |
|
if (curChar == CR) |
|
{ |
|
if (nextChar == LF) |
|
{ |
|
length = 2; |
|
type = UnicodeNewline.CRLF; |
|
} |
|
else |
|
{ |
|
length = 1; |
|
type = UnicodeNewline.CR; |
|
|
|
} |
|
return true; |
|
} |
|
|
|
switch (curChar) |
|
{ |
|
case LF: |
|
type = UnicodeNewline.LF; |
|
length = 1; |
|
return true; |
|
case NEL: |
|
type = UnicodeNewline.NEL; |
|
length = 1; |
|
return true; |
|
case VT: |
|
type = UnicodeNewline.VT; |
|
length = 1; |
|
return true; |
|
case FF: |
|
type = UnicodeNewline.FF; |
|
length = 1; |
|
return true; |
|
case LS: |
|
type = UnicodeNewline.LS; |
|
length = 1; |
|
return true; |
|
case PS: |
|
type = UnicodeNewline.PS; |
|
length = 1; |
|
return true; |
|
} |
|
length = -1; |
|
type = UnicodeNewline.Unknown; |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the new line type of a given char/next char. |
|
/// </summary> |
|
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns> |
|
/// <param name="curChar">The current character.</param> |
|
/// <param name="nextChar">A callback getting the next character (may be null).</param> |
|
public static UnicodeNewline GetDelimiterType(char curChar, Func<char>? nextChar = null) |
|
{ |
|
switch (curChar) |
|
{ |
|
case CR: |
|
if (nextChar != null && nextChar() == LF) |
|
return UnicodeNewline.CRLF; |
|
return UnicodeNewline.CR; |
|
case LF: |
|
return UnicodeNewline.LF; |
|
case NEL: |
|
return UnicodeNewline.NEL; |
|
case VT: |
|
return UnicodeNewline.VT; |
|
case FF: |
|
return UnicodeNewline.FF; |
|
case LS: |
|
return UnicodeNewline.LS; |
|
case PS: |
|
return UnicodeNewline.PS; |
|
} |
|
return UnicodeNewline.Unknown; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the new line type of a given char/next char. |
|
/// </summary> |
|
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns> |
|
/// <param name="curChar">The current character.</param> |
|
/// <param name="nextChar">The next character (if != LF then length will always be 0 or 1).</param> |
|
public static UnicodeNewline GetDelimiterType(char curChar, char nextChar) |
|
{ |
|
switch (curChar) |
|
{ |
|
case CR: |
|
if (nextChar == LF) |
|
return UnicodeNewline.CRLF; |
|
return UnicodeNewline.CR; |
|
case LF: |
|
return UnicodeNewline.LF; |
|
case NEL: |
|
return UnicodeNewline.NEL; |
|
case VT: |
|
return UnicodeNewline.VT; |
|
case FF: |
|
return UnicodeNewline.FF; |
|
case LS: |
|
return UnicodeNewline.LS; |
|
case PS: |
|
return UnicodeNewline.PS; |
|
} |
|
return UnicodeNewline.Unknown; |
|
} |
|
|
|
/// <summary> |
|
/// Determines if a char is a new line delimiter. |
|
/// |
|
/// Note that the only 2 char wide new line is CR LF and both chars are new line |
|
/// chars on their own. For most cases GetDelimiterLength is the better choice. |
|
/// </summary> |
|
public static bool IsNewLine(char ch) |
|
{ |
|
return |
|
ch == NewLine.CR || |
|
ch == NewLine.LF || |
|
ch == NewLine.NEL || |
|
ch == NewLine.VT || |
|
ch == NewLine.FF || |
|
ch == NewLine.LS || |
|
ch == NewLine.PS; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the new line as a string. |
|
/// </summary> |
|
public static string GetString(UnicodeNewline newLine) |
|
{ |
|
switch (newLine) |
|
{ |
|
case UnicodeNewline.Unknown: |
|
return ""; |
|
case UnicodeNewline.LF: |
|
return "\n"; |
|
case UnicodeNewline.CRLF: |
|
return "\r\n"; |
|
case UnicodeNewline.CR: |
|
return "\r"; |
|
case UnicodeNewline.NEL: |
|
return "\u0085"; |
|
case UnicodeNewline.VT: |
|
return "\u000B"; |
|
case UnicodeNewline.FF: |
|
return "\u000C"; |
|
case UnicodeNewline.LS: |
|
return "\u2028"; |
|
case UnicodeNewline.PS: |
|
return "\u2029"; |
|
default: |
|
throw new ArgumentOutOfRangeException(); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|