@@ -144,7 +144,8 @@ public static int GetMaxSizeOf(string? input, NativeStringEncoding encoding = Na
144
144
NativeStringEncoding . BStr => - 1 ,
145
145
NativeStringEncoding . LPStr or NativeStringEncoding . LPTStr or NativeStringEncoding . LPUTF8Str
146
146
=> ( input is null ? 0 : Encoding . UTF8 . GetMaxByteCount ( input . Length ) ) + 1 ,
147
- NativeStringEncoding . LPWStr => ( ( input ? . Length ?? 0 ) + 1 ) * 2 ,
147
+ NativeStringEncoding . LPWStr when RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) => ( ( input ? . Length ?? 0 ) + 1 ) * 2 ,
148
+ NativeStringEncoding . LPWStr => ( ( input ? . Length ?? 0 ) + 1 ) * 4 ,
148
149
_ => - 1
149
150
} ;
150
151
@@ -188,29 +189,38 @@ public static unsafe int StringIntoSpan
188
189
int convertedBytes ;
189
190
190
191
fixed ( char * firstChar = input )
192
+ fixed ( byte * bytes = span )
191
193
{
192
- fixed ( byte * bytes = span )
193
- {
194
- convertedBytes = Encoding . UTF8 . GetBytes ( firstChar , input . Length , bytes , span . Length - 1 ) ;
195
- }
194
+ convertedBytes = Encoding . UTF8 . GetBytes ( firstChar , input . Length , bytes , span . Length - 1 ) ;
195
+ bytes [ convertedBytes ] = 0 ;
196
196
}
197
197
198
- span [ convertedBytes ] = 0 ;
199
- return ++ convertedBytes ;
198
+ return convertedBytes + 1 ;
200
199
}
201
- case NativeStringEncoding . LPWStr :
200
+ case NativeStringEncoding . LPWStr when RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) :
202
201
{
203
202
fixed ( char * firstChar = input )
203
+ fixed ( byte * bytes = span )
204
204
{
205
- fixed ( byte * bytes = span )
206
- {
207
- Buffer . MemoryCopy ( firstChar , bytes , span . Length , input . Length * 2 ) ;
208
- ( ( char * ) bytes ) [ input . Length ] = default ;
209
- }
205
+ Buffer . MemoryCopy ( firstChar , bytes , span . Length , input . Length * 2 ) ;
206
+ ( ( char * ) bytes ) [ input . Length ] = default ;
210
207
}
211
208
212
209
return input . Length + 1 ;
213
210
}
211
+ case NativeStringEncoding . LPWStr :
212
+ {
213
+ int convertedBytes ;
214
+
215
+ fixed ( char * firstChar = input )
216
+ fixed ( byte * bytes = span )
217
+ {
218
+ convertedBytes = Encoding . UTF32 . GetBytes ( firstChar , input . Length , bytes , span . Length - 4 ) ;
219
+ ( ( uint * ) bytes ) [ convertedBytes / 4 ] = 0 ;
220
+ }
221
+
222
+ return convertedBytes + 4 ;
223
+ }
214
224
default :
215
225
{
216
226
ThrowInvalidEncoding < GlobalMemory > ( ) ;
@@ -311,7 +321,19 @@ static unsafe string BStrToString(nint ptr)
311
321
=> new string ( ( char * ) ptr , 0 , ( int ) ( * ( ( uint * ) ptr - 1 ) / sizeof ( char ) ) ) ;
312
322
313
323
static unsafe string AnsiToString( nint ptr ) => new string ( ( sbyte * ) ptr ) ;
314
- static unsafe string WideToString( nint ptr ) => new string ( ( char * ) ptr ) ;
324
+
325
+ static unsafe string WideToString( nint ptr )
326
+ {
327
+ if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
328
+ {
329
+ return new string ( ( char * ) ptr ) ;
330
+ }
331
+ else
332
+ {
333
+ var length = StringLength ( ptr , NativeStringEncoding . LPWStr ) ;
334
+ return Encoding . UTF32 . GetString ( ( byte * ) ptr , 4 * ( int ) length ) ;
335
+ }
336
+ } ;
315
337
}
316
338
317
339
/// <summary>
@@ -524,15 +546,41 @@ Func<nint, string> customUnmarshaller
524
546
/// </remarks>
525
547
#if NET6_0_OR_GREATER
526
548
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
527
- public static unsafe nuint StringLength (
549
+ public static unsafe nuint StringLength
550
+ (
528
551
nint ptr ,
529
552
NativeStringEncoding encoding = NativeStringEncoding . Ansi
530
- ) =>
531
- ( nuint ) (
532
- encoding == NativeStringEncoding . LPWStr
533
- ? MemoryMarshal . CreateReadOnlySpanFromNullTerminated ( ( char * ) ptr ) . Length
534
- : MemoryMarshal . CreateReadOnlySpanFromNullTerminated ( ( byte * ) ptr ) . Length
535
- ) ;
553
+ )
554
+ {
555
+ switch ( encoding )
556
+ {
557
+ default :
558
+ {
559
+ return ( nuint ) MemoryMarshal . CreateReadOnlySpanFromNullTerminated ( ( byte * ) ptr ) . Length ;
560
+ }
561
+ case NativeStringEncoding . LPWStr when RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) :
562
+ {
563
+ return ( nuint ) MemoryMarshal . CreateReadOnlySpanFromNullTerminated ( ( char * ) ptr ) . Length ;
564
+ }
565
+ case NativeStringEncoding . LPWStr :
566
+ {
567
+ // No int overload for CreateReadOnlySpanFromNullTerminated
568
+ if ( ptr == 0 )
569
+ {
570
+ return 0 ;
571
+ }
572
+
573
+ nuint length = 0 ;
574
+ while ( ( ( uint * ) ptr ) ! [ length ] != 0 )
575
+ {
576
+ length ++ ;
577
+ }
578
+
579
+ return length ;
580
+ }
581
+ }
582
+ }
583
+
536
584
#else
537
585
public static unsafe nuint StringLength (
538
586
nint ptr ,
@@ -543,15 +591,40 @@ public static unsafe nuint StringLength(
543
591
{
544
592
return 0 ;
545
593
}
546
- nuint ret ;
547
- for (
548
- ret = 0 ;
549
- encoding == NativeStringEncoding . LPWStr
550
- ? ( ( char * ) ptr ) ! [ ret ] != 0
551
- : ( ( byte * ) ptr ) ! [ ret ] != 0 ;
552
- ret ++
553
- ) { }
554
- return ret ;
594
+
595
+ nuint length = 0 ;
596
+ switch ( encoding )
597
+ {
598
+ default :
599
+ {
600
+ while ( ( ( byte * ) ptr ) ! [ length ] != 0 )
601
+ {
602
+ length ++ ;
603
+ }
604
+
605
+ break ;
606
+ }
607
+ case NativeStringEncoding . LPWStr when RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) :
608
+ {
609
+ while ( ( ( char * ) ptr ) ! [ length ] != 0 )
610
+ {
611
+ length ++ ;
612
+ }
613
+
614
+ break ;
615
+ }
616
+ case NativeStringEncoding . LPWStr :
617
+ {
618
+ while ( ( ( uint * ) ptr ) ! [ length ] != 0 )
619
+ {
620
+ length ++ ;
621
+ }
622
+
623
+ break ;
624
+ }
625
+ }
626
+
627
+ return length ;
555
628
}
556
629
#endif
557
630
0 commit comments