Skip to content

Commit f671d24

Browse files
committed
Add LuaTableTextReader.
Bug fix in StringDelimiterInfo.
1 parent c0a798d commit f671d24

File tree

8 files changed

+1160
-48
lines changed

8 files changed

+1160
-48
lines changed

Luaon.Json/JsonLuaWriter.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ public override void WriteNull()
197197
writer.Write(LuaConvert.Nil);
198198
}
199199

200+
/// <inheritdoc />
200201
public override void WriteUndefined()
201202
{
202203
throw new NotSupportedException();
@@ -218,7 +219,7 @@ public override void WriteValue(string value)
218219
if (value == null)
219220
writer.Write(LuaConvert.Nil);
220221
else
221-
writer.Write(LuaConvert.ToString(value));
222+
LuaConvert.WriteString(writer, value);
222223
}
223224

224225
/// <inheritdoc />

Luaon.NET/Exceptions.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,67 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont
8484
/// </summary>
8585
public virtual string Path { get; }
8686

87+
/// <inheritdoc />
88+
public override string Message
89+
{
90+
get
91+
{
92+
if (!string.IsNullOrEmpty(Path))
93+
return base.Message + "\nPath: " + Path;
94+
return base.Message;
95+
}
96+
}
97+
}
98+
99+
#if NETSTANDARD2_0
100+
[Serializable]
101+
#endif
102+
public class LuaTableReaderException : LuaonException
103+
{
104+
105+
public LuaTableReaderException()
106+
{
107+
}
108+
109+
public LuaTableReaderException(string message) : this(message, null, null)
110+
{
111+
}
112+
113+
public LuaTableReaderException(string message, string path) : this(message, path, null)
114+
{
115+
}
116+
117+
public LuaTableReaderException(string message, Exception inner) : this(message, null, inner)
118+
{
119+
}
120+
121+
public LuaTableReaderException(string message, string path, Exception inner) : base(message)
122+
{
123+
Path = path;
124+
}
125+
126+
#if NETSTANDARD2_0
127+
[SecurityCritical]
128+
protected LuaTableReaderException(
129+
SerializationInfo info,
130+
StreamingContext context) : base(info, context)
131+
{
132+
Path = info.GetString("Path");
133+
}
134+
135+
/// <inheritdoc />
136+
public override void GetObjectData(SerializationInfo info, StreamingContext context)
137+
{
138+
base.GetObjectData(info, context);
139+
info.AddValue("Path", Path);
140+
}
141+
#endif
142+
143+
/// <summary>
144+
/// Gets the Lua property path where the exception happens.
145+
/// </summary>
146+
public virtual string Path { get; }
147+
87148
/// <inheritdoc />
88149
public override string Message
89150
{

Luaon.NET/LuaContainerContext.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@ internal struct LuaContainerContext
1717

1818
public readonly LuaContainerType ContainerType;
1919

20-
// Key != null: Named field; Key == null: Indexed field.
20+
// Key != null: Named field; Key == null && BoxedKey == null: Indexed field.
21+
// This is used in Writer.
2122
public string Key;
2223

24+
// The effective value of the key, boxed as object.
25+
// This is used in Reader.
26+
public object BoxedKey;
27+
2328
public bool KeyIsExpression;
2429

2530
public int CurrentIndex;
@@ -28,20 +33,32 @@ public LuaContainerContext(LuaContainerType containerType)
2833
{
2934
ContainerType = containerType;
3035
Key = null;
36+
BoxedKey = null;
3137
KeyIsExpression = true;
3238
CurrentIndex = 1;
3339
}
3440

3541
/// <inheritdoc />
3642
public override string ToString()
3743
{
44+
if (ContainerType == LuaContainerType.None)
45+
return "<Root>";
3846
var sb = new StringBuilder();
3947
ToString(sb);
4048
return sb.ToString();
4149
}
4250

4351
private void ToString(StringBuilder sb)
4452
{
53+
if (ContainerType == LuaContainerType.None)
54+
{
55+
sb.Append("<Root>");
56+
return;
57+
}
58+
if (Key == null && BoxedKey != null)
59+
{
60+
Key = BoxedKey.ToString();
61+
}
4562
if (Key == null)
4663
{
4764
sb.Append('[');

Luaon.NET/LuaConvert.cs

Lines changed: 90 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,17 @@ public static string ToString(object value)
407407

408408
#endregion
409409

410+
public static void WriteString(TextWriter writer, string value)
411+
{
412+
WriteEscapedString(value, StringDelimiterInfo.DoubleQuote, writer);
413+
}
414+
415+
public static void WriteString(TextWriter writer, string value, string delimiter)
416+
{
417+
var delm = StringDelimiterInfo.FromStartDelimiter(delimiter);
418+
WriteEscapedString(value, delm, writer);
419+
}
420+
410421
internal static void WriteEscapedString(string value, StringDelimiterInfo delimiter, TextWriter writer)
411422
{
412423
Debug.Assert(delimiter != null);
@@ -433,6 +444,9 @@ internal static void WriteEscapedString(string value, StringDelimiterInfo delimi
433444
{
434445
switch (c)
435446
{
447+
case '\\':
448+
writer.Write("\\");
449+
break;
436450
case '\a':
437451
writer.Write("\\a");
438452
break;
@@ -473,52 +487,93 @@ internal static void WriteEscapedString(string value, StringDelimiterInfo delimi
473487

474488
internal sealed class StringDelimiterInfo : IEquatable<StringDelimiterInfo>
475489
{
476-
477-
private readonly int data;
478-
479490
public static readonly StringDelimiterInfo SingleQuote = new StringDelimiterInfo(-1, "'", "'");
480491
public static readonly StringDelimiterInfo DoubleQuote = new StringDelimiterInfo(-2, "\"", "\"");
481492
public static readonly StringDelimiterInfo Brackets0 = new StringDelimiterInfo(0, "[[", "]]");
482-
public static readonly StringDelimiterInfo Brackets1 = new StringDelimiterInfo(0, "[=[", "]=]");
483-
public static readonly StringDelimiterInfo Brackets2 = new StringDelimiterInfo(0, "[==[", "]==]");
484-
public static readonly StringDelimiterInfo Brackets3 = new StringDelimiterInfo(0, "[===[", "]===]");
485-
public static readonly StringDelimiterInfo Brackets4 = new StringDelimiterInfo(0, "[====[", "]====]");
493+
public static readonly StringDelimiterInfo Brackets1 = new StringDelimiterInfo(1, "[=[", "]=]");
494+
public static readonly StringDelimiterInfo Brackets2 = new StringDelimiterInfo(2, "[==[", "]==]");
495+
public static readonly StringDelimiterInfo Brackets3 = new StringDelimiterInfo(3, "[===[", "]===]");
496+
public static readonly StringDelimiterInfo Brackets4 = new StringDelimiterInfo(4, "[====[", "]====]");
497+
public static readonly StringDelimiterInfo Brackets5 = new StringDelimiterInfo(5, "[=====[", "]=====]");
498+
public static readonly StringDelimiterInfo Brackets6 = new StringDelimiterInfo(6, "[======[", "]======]");
499+
public static readonly StringDelimiterInfo Brackets7 = new StringDelimiterInfo(7, "[=======[", "]=======]");
500+
public static readonly StringDelimiterInfo Brackets8 = new StringDelimiterInfo(8, "[========[", "]========]");
501+
502+
private static readonly StringDelimiterInfo[] bracketsByLevel =
503+
{
504+
Brackets0,
505+
Brackets1,
506+
Brackets2,
507+
Brackets3,
508+
Brackets4,
509+
Brackets5,
510+
Brackets6,
511+
Brackets7,
512+
Brackets8,
513+
};
486514

487515
public static StringDelimiterInfo FromStartDelimiter(string delimiter)
488516
{
489517
if (delimiter == null) throw new ArgumentNullException(nameof(delimiter));
490518
if (delimiter.Length == 0) goto INVALID_DELIMITER;
491-
switch (delimiter)
519+
if (delimiter.Length <= 10)
492520
{
493-
case "'": return new StringDelimiterInfo(-1, "'", "'");
494-
case "\"": return new StringDelimiterInfo(-2, "\"", "\"");
495-
case "[[": return new StringDelimiterInfo(0, "[[", "]]");
496-
case "[=[": return new StringDelimiterInfo(1, "[=[", "]=]");
497-
case "[==[": return new StringDelimiterInfo(2, "[==[", "]==]");
498-
case "[===[": return new StringDelimiterInfo(3, "[===[", "]===]");
499-
case "[====[": return new StringDelimiterInfo(4, "[====[", "]====]");
500-
case "[=====[": return new StringDelimiterInfo(5, "[=====[", "]=====]");
501-
case "[======[": return new StringDelimiterInfo(6, "[======[", "]======]");
502-
case "[=======[": return new StringDelimiterInfo(7, "[=======[", "]=======]");
503-
case "[========[": return new StringDelimiterInfo(8, "[========[", "]========]");
504-
default:
505-
if (delimiter[0] != '[') goto INVALID_DELIMITER;
506-
if (delimiter[delimiter.Length - 1] != '[') goto INVALID_DELIMITER;
507-
for (int i = 1; i < delimiter.Length - 1; i++) if (delimiter[i] != '=') goto INVALID_DELIMITER;
508-
var sb = new StringBuilder("]", delimiter.Length);
509-
sb.Append('=', delimiter.Length - 2);
510-
sb.Append(']');
511-
return new StringDelimiterInfo(delimiter.Length - 2, delimiter, sb.ToString());
521+
switch (delimiter)
522+
{
523+
case "'": return SingleQuote;
524+
case "\"": return DoubleQuote;
525+
case "[[": return Brackets0;
526+
case "[=[": return Brackets1;
527+
case "[==[": return Brackets2;
528+
case "[===[": return Brackets3;
529+
case "[====[": return Brackets4;
530+
case "[=====[": return Brackets5;
531+
case "[======[": return Brackets6;
532+
case "[=======[": return Brackets7;
533+
case "[========[": return Brackets8;
534+
default: goto INVALID_DELIMITER;
535+
}
512536
}
513-
INVALID_DELIMITER:
537+
if (delimiter[0] != '[') goto INVALID_DELIMITER;
538+
if (delimiter[delimiter.Length - 1] != '[') goto INVALID_DELIMITER;
539+
for (int i = 1; i < delimiter.Length - 1; i++)
540+
if (delimiter[i] != '=')
541+
goto INVALID_DELIMITER;
542+
var sb = new StringBuilder("]", delimiter.Length);
543+
sb.Append('=', delimiter.Length - 2);
544+
sb.Append(']');
545+
return new StringDelimiterInfo(delimiter.Length - 2, delimiter, sb.ToString());
546+
INVALID_DELIMITER:
514547
throw new ArgumentException("Invalid string delimiter.", nameof(delimiter));
515548
}
516549

550+
public static StringDelimiterInfo FromBracketLevel(int bracketLevel)
551+
{
552+
switch (bracketLevel)
553+
{
554+
case -2: return DoubleQuote;
555+
case -1: return SingleQuote;
556+
default:
557+
if (bracketLevel < 0)
558+
throw new ArgumentException("Invalid bracket level.", nameof(bracketLevel));
559+
if (bracketLevel < bracketsByLevel.Length)
560+
return bracketsByLevel[bracketLevel];
561+
var sb = new StringBuilder("[", bracketLevel + 2);
562+
sb.Append('=', bracketLevel);
563+
sb.Append('[');
564+
var startDelm = sb.ToString();
565+
sb[0] = ']';
566+
sb[sb.Length - 1] = ']';
567+
var endDelim = sb.ToString();
568+
return new StringDelimiterInfo(bracketLevel, startDelm, endDelim);
569+
}
570+
}
571+
517572
private StringDelimiterInfo(int data, string startDelimiter, string endDelimiter)
518573
{
519574
Debug.Assert(startDelimiter != null);
520575
Debug.Assert(endDelimiter != null);
521-
this.data = data;
576+
this.BracketLevel = data;
522577
StartDelimiter = startDelimiter;
523578
EndDelimiter = endDelimiter;
524579
}
@@ -527,20 +582,20 @@ private StringDelimiterInfo(int data, string startDelimiter, string endDelimiter
527582

528583
public string EndDelimiter { get; }
529584

530-
public bool IsSingleQuote => data == -1;
585+
public bool IsSingleQuote => BracketLevel == -1;
531586

532-
public bool IsDoubleQuote => data == -2;
587+
public bool IsDoubleQuote => BracketLevel == -2;
533588

534-
public bool IsBracket => data >= 0;
589+
public bool IsBracket => BracketLevel >= 0;
535590

536-
public int BracketLevel => data;
591+
public int BracketLevel { get; }
537592

538593
/// <inheritdoc />
539594
public bool Equals(StringDelimiterInfo other)
540595
{
541596
if (ReferenceEquals(null, other)) return false;
542597
if (ReferenceEquals(this, other)) return true;
543-
return data == other.data;
598+
return BracketLevel == other.BracketLevel;
544599
}
545600

546601
/// <inheritdoc />
@@ -554,7 +609,7 @@ public override bool Equals(object obj)
554609
/// <inheritdoc />
555610
public override int GetHashCode()
556611
{
557-
return data;
612+
return BracketLevel;
558613
}
559614

560615
public static bool operator ==(StringDelimiterInfo left, StringDelimiterInfo right)

0 commit comments

Comments
 (0)