Browse Source

Fix: string.format ('%q' format)

AnnulusGames 1 year ago
parent
commit
f2f55c2d33
2 changed files with 61 additions and 9 deletions
  1. 60 7
      src/Lua/Internal/StringHelper.cs
  2. 1 2
      src/Lua/Standard/Text/FormatFunction.cs

+ 60 - 7
src/Lua/Internal/StringHelper.cs

@@ -33,6 +33,17 @@ internal static class StringHelper
 
 
                 switch (c)
                 switch (c)
                 {
                 {
+                    case '\n':
+                        builder.Append('\n');
+                        break;
+                    case '\r':
+                        builder.Append('\r');
+                        // check CRLF
+                        if (i + 1 < literal.Length && literal[i + 1] is '\n')
+                        {
+                            i++;
+                        }
+                        break;
                     case 'a':
                     case 'a':
                         builder.Append('\a');
                         builder.Append('\a');
                         break;
                         break;
@@ -131,6 +142,55 @@ internal static class StringHelper
         return true;
         return true;
     }
     }
 
 
+    public static string Escape(ReadOnlySpan<char> str)
+    {
+        var builder = new ValueStringBuilder(str.Length);
+
+        for (int i = 0; i < str.Length; i++)
+        {
+            var c = str[i];
+
+            switch (c)
+            {
+                case '\a':
+                    builder.Append("\\\a");
+                    break;
+                case '\b':
+                    builder.Append("\\\b");
+                    break;
+                case '\f':
+                    builder.Append("\\\f");
+                    break;
+                case '\n':
+                    builder.Append("\\\n");
+                    break;
+                case '\r':
+                    builder.Append("\\\r");
+                    break;
+                case '\t':
+                    builder.Append("\\\t");
+                    break;
+                case '\v':
+                    builder.Append("\\\v");
+                    break;
+                case '\\':
+                    builder.Append("\\\\");
+                    break;
+                case '\"':
+                    builder.Append("\\\"");
+                    break;
+                case '\'':
+                    builder.Append("\\\'");
+                    break;
+                default:
+                    builder.Append(c);
+                    break;
+            }
+        }
+
+        return builder.ToString();
+    }
+
     public static Regex ToRegex(ReadOnlySpan<char> pattern)
     public static Regex ToRegex(ReadOnlySpan<char> pattern)
     {
     {
         var builder = new ValueStringBuilder();
         var builder = new ValueStringBuilder();
@@ -164,49 +224,42 @@ internal static class StringHelper
                         case 'S': // all NON space characters
                         case 'S': // all NON space characters
                             builder.Append("\\S");
                             builder.Append("\\S");
                             break;
                             break;
-
                         case 'd': // all digits
                         case 'd': // all digits
                             builder.Append("\\d");
                             builder.Append("\\d");
                             break;
                             break;
                         case 'D': // all NON digits
                         case 'D': // all NON digits
                             builder.Append("\\D");
                             builder.Append("\\D");
                             break;
                             break;
-
                         case 'w': // all alphanumeric characters
                         case 'w': // all alphanumeric characters
                             builder.Append("\\w");
                             builder.Append("\\w");
                             break;
                             break;
                         case 'W': // all NON alphanumeric characters
                         case 'W': // all NON alphanumeric characters
                             builder.Append("\\W");
                             builder.Append("\\W");
                             break;
                             break;
-
                         case 'c': // all control characters
                         case 'c': // all control characters
                             builder.Append("\\p{C}");
                             builder.Append("\\p{C}");
                             break;
                             break;
                         case 'C': // all NON control characters
                         case 'C': // all NON control characters
                             builder.Append("[\\P{C}]");
                             builder.Append("[\\P{C}]");
                             break;
                             break;
-
                         case 'g': // all printable characters except space
                         case 'g': // all printable characters except space
                             builder.Append("[^\\p{C}\\s]");
                             builder.Append("[^\\p{C}\\s]");
                             break;
                             break;
                         case 'G': // all NON printable characters including space
                         case 'G': // all NON printable characters including space
                             builder.Append("[\\p{C}\\s]");
                             builder.Append("[\\p{C}\\s]");
                             break;
                             break;
-
                         case 'p': // all punctuation characters
                         case 'p': // all punctuation characters
                             builder.Append("\\p{P}");
                             builder.Append("\\p{P}");
                             break;
                             break;
                         case 'P': // all NON punctuation characters
                         case 'P': // all NON punctuation characters
                             builder.Append("\\P{P}");
                             builder.Append("\\P{P}");
                             break;
                             break;
-
                         case 'l': // all lowercase letters
                         case 'l': // all lowercase letters
                             builder.Append("\\p{Ll}");
                             builder.Append("\\p{Ll}");
                             break;
                             break;
                         case 'L': // all NON lowercase letters
                         case 'L': // all NON lowercase letters
                             builder.Append("\\P{Ll}");
                             builder.Append("\\P{Ll}");
                             break;
                             break;
-
                         case 'u': // all uppercase letters
                         case 'u': // all uppercase letters
                             builder.Append("\\p{Lu}");
                             builder.Append("\\p{Lu}");
                             break;
                             break;

+ 1 - 2
src/Lua/Standard/Text/FormatFunction.cs

@@ -154,8 +154,7 @@ public sealed class FormatFunction : LuaFunction
                                 formattedValue = parameter.Read<bool>() ? "true" : "false";
                                 formattedValue = parameter.Read<bool>() ? "true" : "false";
                                 break;
                                 break;
                             case LuaValueType.String:
                             case LuaValueType.String:
-                                // TODO: support escape sequence
-                                formattedValue = parameter.Read<string>();
+                                formattedValue = $"\"{StringHelper.Escape(parameter.Read<string>())}\"";
                                 break;
                                 break;
                             case LuaValueType.Number:
                             case LuaValueType.Number:
                                 // TODO: floating point numbers must be in hexadecimal notation
                                 // TODO: floating point numbers must be in hexadecimal notation