@@ -37,7 +37,7 @@ public class CSharpCodeGenerator : ICodeGenerator
3737 [ typeof ( Vector2Node ) ] = "Vector2" ,
3838 [ typeof ( Vector3Node ) ] = "Vector3" ,
3939 [ typeof ( Vector4Node ) ] = "Vector4"
40- } ;
40+ } ;
4141
4242 public Language Language => Language . CSharp ;
4343
@@ -77,21 +77,42 @@ public string GenerateCode(IReadOnlyList<ClassNode> classes, IReadOnlyList<EnumD
7777 . Where ( c => c . Nodes . None ( n => n is FunctionNode ) ) // Skip class which contains FunctionNodes because these are not data classes.
7878 . Distinct ( ) ;
7979
80+ var unicodeStringClassLengthsToGenerate = new HashSet < int > ( ) ;
81+
8082 using ( var en = classesToWrite . GetEnumerator ( ) )
8183 {
8284 if ( en . MoveNext ( ) )
8385 {
86+ void FindUnicodeStringClasses ( IEnumerable < BaseNode > nodes )
87+ {
88+ unicodeStringClassLengthsToGenerate . UnionWith ( nodes . OfType < Utf16TextNode > ( ) . Select ( n => n . Length ) ) ;
89+ }
90+
91+ FindUnicodeStringClasses ( en . Current ! . Nodes ) ;
92+
8493 WriteClass ( iw , en . Current , logger ) ;
8594
8695 while ( en . MoveNext ( ) )
8796 {
8897 iw . WriteLine ( ) ;
8998
99+ FindUnicodeStringClasses ( en . Current ! . Nodes ) ;
100+
90101 WriteClass ( iw , en . Current , logger ) ;
91102 }
92103 }
93104 }
94105
106+ if ( unicodeStringClassLengthsToGenerate . Any ( ) )
107+ {
108+ foreach ( var length in unicodeStringClassLengthsToGenerate )
109+ {
110+ iw . WriteLine ( ) ;
111+
112+ WriteUnicodeStringClass ( iw , length ) ;
113+ }
114+ }
115+
95116 return sw . ToString ( ) ;
96117 }
97118
@@ -152,7 +173,7 @@ private static void WriteClass(IndentedTextWriter writer, ClassNode @class, ILog
152173 Contract . Requires ( @class != null ) ;
153174 Contract . Requires ( logger != null ) ;
154175
155- writer . WriteLine ( "[StructLayout(LayoutKind.Explicit)]" ) ;
176+ writer . WriteLine ( "[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi )]" ) ;
156177 writer . Write ( "public struct " ) ;
157178 writer . Write ( @class . Name ) ;
158179
@@ -199,10 +220,10 @@ private static void WriteClass(IndentedTextWriter writer, ClassNode @class, ILog
199220 }
200221
201222 /// <summary>
202- /// Gets the type definition for the given node. If the node is not a simple node <c>null</c> is returned.
223+ /// Gets the type definition for the given node. If the node is not expressible <c>null</c> as typename is returned.
203224 /// </summary>
204225 /// <param name="node">The target node.</param>
205- /// <returns>The type definition for the node or null if no simple type is available .</returns>
226+ /// <returns>The type definition for the node or null as typename if the node is not expressible .</returns>
206227 private static ( string typeName , string attribute ) GetTypeDefinition ( BaseNode node )
207228 {
208229 Contract . Requires ( node != null ) ;
@@ -219,17 +240,36 @@ private static (string typeName, string attribute) GetTypeDefinition(BaseNode no
219240 return ( type , null ) ;
220241 }
221242
222- if ( node is EnumNode enumNode )
243+ return node switch
223244 {
224- return ( enumNode . Enum . Name , null ) ;
225- }
245+ EnumNode enumNode => ( enumNode . Enum . Name , null ) ,
246+ Utf8TextNode utf8TextNode => ( "string" , $ "[MarshalAs(UnmanagedType.ByValTStr, SizeConst = { utf8TextNode . Length } )]") ,
247+ Utf16TextNode utf16TextNode => ( GetUnicodeStringClassName ( utf16TextNode . Length ) , "[MarshalAs(UnmanagedType.Struct)]" ) ,
248+ _ => ( null , null )
249+ } ;
250+ }
226251
227- if ( node is Utf8TextNode utf8TextNode )
228- {
229- return ( "string" , $ "[MarshalAs(UnmanagedType.ByValTStr, SizeConst = { utf8TextNode . Length } )]") ;
230- }
252+ private static string GetUnicodeStringClassName ( int length ) => $ "__UnicodeString{ length } ";
231253
232- return ( null , null ) ;
254+ /// <summary>
255+ /// Writes a helper class for unicode strings with the specific length.
256+ /// </summary>
257+ /// <param name="writer">The writer to output to.</param>
258+ /// <param name="length">The string length for this class.</param>
259+ private static void WriteUnicodeStringClass ( IndentedTextWriter writer , int length )
260+ {
261+ var className = GetUnicodeStringClassName ( length ) ;
262+
263+ writer . WriteLine ( "[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]" ) ;
264+ writer . WriteLine ( $ "public struct { className } ") ;
265+ writer . WriteLine ( "{" ) ;
266+ writer . Indent ++ ;
267+ writer . WriteLine ( $ "[MarshalAs(UnmanagedType.ByValTStr, SizeConst = { length } )]") ;
268+ writer . WriteLine ( "public string Value;" ) ;
269+ writer . WriteLine ( ) ;
270+ writer . WriteLine ( $ "public static implicit operator string({ className } value) => value.Value;") ;
271+ writer . Indent -- ;
272+ writer . WriteLine ( "}" ) ;
233273 }
234274 }
235275}
0 commit comments