@@ -154,6 +154,16 @@ public void __init__(CodeContext/*!*/ context, object fmt) {
154154 WritePointer ( res , _isLittleEndian , GetPointer ( context , curObj ++ , values ) ) ;
155155 }
156156 break ;
157+ case FormatType . SignedSizeT :
158+ for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
159+ WriteSignedSizeT ( res , _isLittleEndian , GetSignedSizeT ( context , curObj ++ , values ) ) ;
160+ }
161+ break ;
162+ case FormatType . SizeT :
163+ for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
164+ WriteSizeT ( res , _isLittleEndian , GetSizeT ( context , curObj ++ , values ) ) ;
165+ }
166+ break ;
157167 case FormatType . LongLong :
158168 for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
159169 WriteLong ( res , _isLittleEndian , GetLongValue ( context , curObj ++ , values ) ) ;
@@ -292,6 +302,24 @@ public void pack_into(CodeContext/*!*/ context, [NotNull]ByteArray/*!*/ buffer,
292302 }
293303 }
294304 break ;
305+ case FormatType . SignedSizeT :
306+ for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
307+ if ( IntPtr . Size == 4 ) {
308+ res [ res_idx ++ ] = CreateIntValue ( context , ref curIndex , _isLittleEndian , data ) ;
309+ } else {
310+ res [ res_idx ++ ] = BigIntegerOps . __int__ ( CreateLongValue ( context , ref curIndex , _isLittleEndian , data ) ) ;
311+ }
312+ }
313+ break ;
314+ case FormatType . SizeT :
315+ for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
316+ if ( IntPtr . Size == 4 ) {
317+ res [ res_idx ++ ] = CreateUIntValue ( context , ref curIndex , _isLittleEndian , data ) ;
318+ } else {
319+ res [ res_idx ++ ] = BigIntegerOps . __int__ ( CreateULongValue ( context , ref curIndex , _isLittleEndian , data ) ) ;
320+ }
321+ }
322+ break ;
295323 case FormatType . LongLong :
296324 for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
297325 res [ res_idx ++ ] = BigIntegerOps . __int__ ( CreateLongValue ( context , ref curIndex , _isLittleEndian , data ) ) ;
@@ -450,6 +478,22 @@ private static Struct CompileAndCache(CodeContext/*!*/ context, string/*!*/ fmt)
450478 res . Add ( new Format ( FormatType . Pointer , count ) ) ;
451479 count = 1 ;
452480 break ;
481+ case 'n' : // intptr_t
482+ if ( fStandardized ) {
483+ // n and N don't exist in standard sizes
484+ throw Error ( context , "bad char in struct format" ) ;
485+ }
486+ res . Add ( new Format ( FormatType . SignedSizeT , count ) ) ;
487+ count = 1 ;
488+ break ;
489+ case 'N' : // uintptr_t
490+ if ( fStandardized ) {
491+ // n and N don't exist in standard sizes
492+ throw Error ( context , "bad char in struct format" ) ;
493+ }
494+ res . Add ( new Format ( FormatType . SizeT , count ) ) ;
495+ count = 1 ;
496+ break ;
453497 case ' ' : // white space, ignore
454498 case '\t ' :
455499 break ;
@@ -567,6 +611,9 @@ private enum FormatType {
567611 CString ,
568612 PascalString ,
569613 Pointer ,
614+
615+ SignedSizeT ,
616+ SizeT ,
570617 }
571618
572619 private static int GetNativeSize ( FormatType c ) {
@@ -592,7 +639,10 @@ private static int GetNativeSize(FormatType c) {
592639 case FormatType . Double :
593640 return 8 ;
594641 case FormatType . Pointer :
642+ case FormatType . SignedSizeT :
595643 return IntPtr . Size ;
644+ case FormatType . SizeT :
645+ return UIntPtr . Size ;
596646 default :
597647 throw new InvalidOperationException ( c . ToString ( ) ) ;
598648 }
@@ -747,6 +797,22 @@ private static void WriteUInt(this MemoryStream res, bool fLittleEndian, uint va
747797 }
748798 }
749799
800+ private static void WriteSignedSizeT ( this MemoryStream res , bool fLittleEndian , IntPtr val ) {
801+ if ( IntPtr . Size == 4 ) {
802+ res . WriteInt ( fLittleEndian , val . ToInt32 ( ) ) ;
803+ } else {
804+ res . WriteLong ( fLittleEndian , val . ToInt64 ( ) ) ;
805+ }
806+ }
807+
808+ private static void WriteSizeT ( this MemoryStream res , bool fLittleEndian , UIntPtr val ) {
809+ if ( IntPtr . Size == 4 ) {
810+ res . WriteUInt ( fLittleEndian , val . ToUInt32 ( ) ) ;
811+ } else {
812+ res . WriteULong ( fLittleEndian , val . ToUInt64 ( ) ) ;
813+ }
814+ }
815+
750816 private static void WritePointer ( this MemoryStream res , bool fLittleEndian , IntPtr val ) {
751817 if ( IntPtr . Size == 4 ) {
752818 res . WriteInt ( fLittleEndian , val . ToInt32 ( ) ) ;
@@ -950,6 +1016,34 @@ private static void OutOfRange(CodeContext context, string type) {
9501016 throw Error ( context , $ "integer out of range for '{ ( type == "unsigned long" ? "L" : "I" ) } ' format code") ;
9511017 }
9521018
1019+ internal static IntPtr GetSignedSizeT ( CodeContext /*!*/ context , int index , object [ ] args ) {
1020+ object val = GetValue ( context , index , args ) ;
1021+ if ( IntPtr . Size == 4 ) {
1022+ if ( Converter . TryConvertToInt32 ( val , out int res ) ) {
1023+ return new IntPtr ( res ) ;
1024+ }
1025+ } else {
1026+ if ( Converter . TryConvertToInt64 ( val , out long res ) ) {
1027+ return new IntPtr ( res ) ;
1028+ }
1029+ }
1030+ throw Error ( context , "expected signed size_t(aka ssize_t) value" ) ;
1031+ }
1032+
1033+ internal static UIntPtr GetSizeT ( CodeContext /*!*/ context , int index , object [ ] args ) {
1034+ object val = GetValue ( context , index , args ) ;
1035+ if ( IntPtr . Size == 4 ) {
1036+ if ( Converter . TryConvertToUInt32 ( val , out uint res ) ) {
1037+ return new UIntPtr ( res ) ;
1038+ }
1039+ } else {
1040+ if ( Converter . TryConvertToUInt64 ( val , out ulong res ) ) {
1041+ return new UIntPtr ( res ) ;
1042+ }
1043+ }
1044+ throw Error ( context , "expected size_t value" ) ;
1045+ }
1046+
9531047 internal static IntPtr GetPointer ( CodeContext /*!*/ context , int index , object [ ] args ) {
9541048 object val = GetValue ( context , index , args ) ;
9551049 if ( IntPtr . Size == 4 ) {
0 commit comments