1+ using System . Collections ;
12using System . Globalization ;
23using System . Text ;
34
@@ -42,6 +43,11 @@ internal static string Apply(
4243 continue ;
4344 }
4445
46+ // Do not let entries under an unrecognized table header get
47+ // interpreted as part of the previous known section.
48+ if ( IsTableHeader ( trimmed ) )
49+ currentSection = null ;
50+
4551 if ( currentSection != null
4652 && UsesDisabledFlag ( currentSection )
4753 && IsDisabledEntry ( trimmed ) )
@@ -93,7 +99,7 @@ internal static string Apply(
9399 string trimmed ,
94100 IReadOnlyList < AppleChuConfigSectionSchema > schema )
95101 {
96- var header = trimmed . StartsWith ( "#[" , StringComparison . Ordinal ) ? trimmed [ 1 .. ] : trimmed ;
102+ var header = NormalizeHeader ( trimmed ) ;
97103 if ( header . StartsWith ( '[' ) && header . EndsWith ( ']' )
98104 && ! header . StartsWith ( "[[" , StringComparison . Ordinal ) )
99105 {
@@ -106,6 +112,21 @@ internal static string Apply(
106112 return null ;
107113 }
108114
115+ private static bool IsTableHeader ( string trimmed ) =>
116+ NormalizeHeader ( trimmed ) . StartsWith ( "[" , StringComparison . Ordinal ) ;
117+
118+ private static string NormalizeHeader ( string trimmed )
119+ {
120+ var header = trimmed . StartsWith ( "#[" , StringComparison . Ordinal ) ? trimmed [ 1 .. ] : trimmed ;
121+ if ( ! header . StartsWith ( "[" , StringComparison . Ordinal ) )
122+ return header ;
123+
124+ // A table header may have a trailing comment. Section identifiers in
125+ // the generated schema cannot contain '#', so this is unambiguous.
126+ var comment = header . IndexOf ( '#' ) ;
127+ return comment >= 0 ? header [ .. comment ] . TrimEnd ( ) : header ;
128+ }
129+
109130 private static AppleChuConfigEntrySchema ? FindEntry (
110131 string trimmed ,
111132 AppleChuConfigSectionSchema section )
@@ -212,14 +233,31 @@ private static void AppendEntryLine(StringBuilder output, string line, bool comm
212233 byte or sbyte or short or ushort or int or uint or long or ulong =>
213234 Convert . ToString ( value , CultureInfo . InvariantCulture ) ?? "0" ,
214235 float or double or decimal => Convert . ToString ( value , CultureInfo . InvariantCulture ) ?? "0" ,
215- IEnumerable < object ? > items => $ "[{ string . Join ( ", " , items . Select ( FormatTomlValue ) ) } ]",
236+ IEnumerable items when value is not string =>
237+ $ "[{ string . Join ( ", " , items . Cast < object ? > ( ) . Select ( FormatTomlValue ) ) } ]",
216238 _ => throw new ArgumentException ( "无法写入不受支持的 TOML 值" ) ,
217239 } ;
218240
219- private static string EscapeTomlString ( string value ) => value
220- . Replace ( "\\ " , "\\ \\ " )
221- . Replace ( "\" " , "\\ \" " )
222- . Replace ( "\r " , "\\ r" )
223- . Replace ( "\n " , "\\ n" )
224- . Replace ( "\t " , "\\ t" ) ;
241+ private static string EscapeTomlString ( string value )
242+ {
243+ var escaped = new StringBuilder ( value . Length ) ;
244+ foreach ( var character in value )
245+ {
246+ switch ( character )
247+ {
248+ case '\\ ' : escaped . Append ( "\\ \\ " ) ; break ;
249+ case '"' : escaped . Append ( "\\ \" " ) ; break ;
250+ case '\b ' : escaped . Append ( "\\ b" ) ; break ;
251+ case '\t ' : escaped . Append ( "\\ t" ) ; break ;
252+ case '\n ' : escaped . Append ( "\\ n" ) ; break ;
253+ case '\f ' : escaped . Append ( "\\ f" ) ; break ;
254+ case '\r ' : escaped . Append ( "\\ r" ) ; break ;
255+ case < '\u0020 ' : escaped . Append ( $ "\\ u{ ( int ) character : X4} ") ; break ;
256+ case '\u007f ' : escaped . Append ( "\\ u007F" ) ; break ;
257+ default : escaped . Append ( character ) ; break ;
258+ }
259+ }
260+
261+ return escaped . ToString ( ) ;
262+ }
225263}
0 commit comments