diff --git a/ChangeLog b/ChangeLog index 599618164..59f47cf52 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2024-11-26 Matvii Jarosh + + * NSByteOrder.h: fix NSSwappedFloat and NSSwappedDouble + * MISSING: + +2024-11-25 Matvii Jarosh + + * NSInvocation.h: add enum _NSObjCValueType and + typedef structNSObjCValue. There are no functions not implemented + in NSInvocation.h left. + * MISSING: + +2024-11-21 Matvii Jarosh + + * NSValue: add valueWithEdgeInsets and edgeInsetsValue. + * typeEncodingHelper.h: add NSINSETS_ENCODING_PREFIX and + IS_NSINSETS_ENCODING and update comment. + * type_encoding.m: add test NSINSETS_ENCODING_PREFIX. + * GSConcreteValueTamplate.m: add GSEdgeInsetsValue. + * GSConcreteValue.m: add TYPE_ORDER 6. 2024-11-24 Richard Frith-Macdonald * Source/NSSocketPort.m: fix leak of data object when establishing a diff --git a/Headers/Foundation/NSByteOrder.h b/Headers/Foundation/NSByteOrder.h index ea829585b..918762dff 100644 --- a/Headers/Foundation/NSByteOrder.h +++ b/Headers/Foundation/NSByteOrder.h @@ -384,13 +384,37 @@ NSSwapShort(unsigned short in) static inline NSSwappedDouble NSSwapDouble(NSSwappedDouble num) { +#if GS_SIZEOF_DOUBLE == 2 + return GSSwapI16(num); +#else +#if GS_SIZEOF_DOUBLE == 4 + return GSSwapI32(num); +#else +#if GS_SIZEOF_DOUBLE == 8 return GSSwapI64(num); +#else + return GSSwapI128(num); +#endif +#endif +#endif } static inline NSSwappedFloat NSSwapFloat(NSSwappedFloat num) { +#if GS_SIZEOF_FLOAT == 2 + return GSSwapI16(num); +#else +#if GS_SIZEOF_FLOAT == 4 return GSSwapI32(num); +#else +#if GS_SIZEOF_FLOAT == 8 + return GSSwapI64(num); +#else + return GSSwapI128(num); +#endif +#endif +#endif } #if GS_WORDS_BIGENDIAN diff --git a/Headers/Foundation/NSInvocation.h b/Headers/Foundation/NSInvocation.h index 9b10095d3..9b07b8350 100644 --- a/Headers/Foundation/NSInvocation.h +++ b/Headers/Foundation/NSInvocation.h @@ -27,6 +27,7 @@ #import #import +#include #if defined(__cplusplus) extern "C" { @@ -154,6 +155,47 @@ GS_EXPORT_CLASS [NSInvocation _returnInvocationAndDestroyProxy: __proxy]; \ }) +typedef NS_ENUM(char, _NSObjCValueType) +{ + NSObjCArrayType = '[', + NSObjCBitfield = 'b', + NSObjCBoolType = 'B', + NSObjCCharType = 'c', + NSObjCDoubleType = 'd', + NSObjCFloatType = 'f', + NSObjCLonglongType = 'q', + NSObjCLongType = 'l', + NSObjCNoType = '\0', + NSObjCObjectType = '@', + NSObjCPointerType = '^', + NSObjCSelectorType = ':', + NSObjCShortType = 's', + NSObjCStringType = '*', + NSObjCStructType = '{', + NSObjCUnionType = '(', + NSObjCVoidType = 'v', +}; + +typedef struct +{ + _NSObjCValueType type; + union + { + bool boolValue; + char charValue; + double doubleValue; + float floatValue; + long long longlongValue; + long longValue; + id objectValue; + void *pointerValue; + SEL selectorValue; + short shortValue; + char *cStringLocation; + void *structLocation; + } value; +} NSObjCValue; + #if defined(__cplusplus) } #endif diff --git a/Headers/Foundation/NSValue.h b/Headers/Foundation/NSValue.h index a68b4dfa7..36ce47a11 100644 --- a/Headers/Foundation/NSValue.h +++ b/Headers/Foundation/NSValue.h @@ -96,6 +96,14 @@ GS_EXPORT_CLASS */ + (NSValue*) valueWithSize: (NSSize)size; +#if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) +/** + * Convenience method to create instance holding an NSEdgeInsets + * structure. + */ ++ (NSValue*) valueWithEdgeInsets: (NSEdgeInsets)insets; +#endif + #if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST) /** * Synonym for value:withObjCType: . @@ -166,6 +174,14 @@ GS_EXPORT_CLASS */ - (NSPoint) pointValue; +#if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) +/** + * If receiver was initialized with an NSEdgeInsets value, return it, + * else raises NSInternalInconsistencyException. + */ +- (NSEdgeInsets) edgeInsetsValue; +#endif + @end /** diff --git a/MISSING b/MISSING index cb5f906b0..d53e10c49 100644 --- a/MISSING +++ b/MISSING @@ -32,10 +32,6 @@ NSBundle: /** Not implemented */ (GNUstep comment) - executableArchitectures; ------------------------------------------------------------- -NSByteOrder: - NSSwappedFloat — incompatible declaration - NSSwappedDouble — incompatible declaration -------------------------------------------------------------- NSCalendar: NSWeekOfMonthCalendarUnit NSWeekOfYearCalendarUnit @@ -257,12 +253,7 @@ NSIndexSet: - enumerateRangesUsingBlock: - enumerateRangesWithOptions:usingBlock: - enumerateRangesInRange:options:usingBlock: -------------------------------------------------------------- -NSInvocation: - - enum _NSObjCValueType - typedef struct NSObjCValue ------------------------------------------------------------- NSKeyedArchiver: @@ -885,3 +876,5 @@ Good headers: + + \ No newline at end of file diff --git a/Source/GSConcreteValue.m b/Source/GSConcreteValue.m index a4296da0e..a87488b10 100644 --- a/Source/GSConcreteValue.m +++ b/Source/GSConcreteValue.m @@ -50,3 +50,7 @@ #include "GSConcreteValueTemplate.m" #undef TYPE_ORDER +#define TYPE_ORDER 6 +#include "GSConcreteValueTemplate.m" +#undef TYPE_ORDER + diff --git a/Source/GSConcreteValueTemplate.m b/Source/GSConcreteValueTemplate.m index e29c6b6b3..f93c91273 100644 --- a/Source/GSConcreteValueTemplate.m +++ b/Source/GSConcreteValueTemplate.m @@ -79,6 +79,15 @@ @interface GSSizeValue : NSValue # define GSTemplateValue GSSizeValue # define TYPE_METHOD sizeValue # define TYPE_NAME NSSize +#elif TYPE_ORDER == 6 +@interface GSEdgeInsetsValue : NSValue +{ + NSEdgeInsets data; +} +@end +# define GSTemplateValue GSEdgeInsetsValue +# define TYPE_METHOD edgeInsetsValue +# define TYPE_NAME NSEdgeInsets #endif @implementation GSTemplateValue @@ -164,6 +173,11 @@ - (BOOL) isEqualToValue: (NSValue*)aValue return YES; else return NO; +#elif TYPE_ORDER == 6 + if (data.top == val.top && data.left == val.left && data.bottom == val.bottom && data.right == val.right) + return YES; + else + return NO; #endif } return NO; @@ -213,6 +227,18 @@ - (NSUInteger) hash for (i = 0; i < sizeof(double); i++) hash += val.c[i]; return hash; +#elif TYPE_ORDER == 6 + union { + double d; + unsigned char c[sizeof(double)]; + } val; + NSUInteger hash = 0; + unsigned int i; + + val.d = data.top + data.left + data.bottom + data.right; + for (i = 0; i < sizeof(double); i++) + hash += val.c[i]; + return hash; #endif } @@ -241,6 +267,9 @@ - (NSString *) description return NSStringFromRect(data); #elif TYPE_ORDER == 5 return NSStringFromSize(data); +#elif TYPE_ORDER == 6 + return [NSString stringWithFormat:@"{top = %.2f, left = %.2f, bottom = %.2f, right = %.2f}", + data.top, data.left, data.bottom, data.right]; #endif } diff --git a/Source/NSValue.m b/Source/NSValue.m index f55f0fe39..45069a923 100644 --- a/Source/NSValue.m +++ b/Source/NSValue.m @@ -35,6 +35,7 @@ #import "Foundation/NSMapTable.h" #import "Foundation/NSLock.h" #import "Foundation/NSData.h" +#import "Foundation/NSGeometry.h" #import "GSPThread.h" @interface GSPlaceholderValue : NSValue @@ -64,6 +65,11 @@ @interface GSSizeValue : NSObject // Help the compiler @class NSDataStatic; // Needed for decoding. @interface NSDataStatic : NSData // Help the compiler @end +#if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) +@class GSEdgeInsetsValueValue; +@interface GSEdgeInsetsValue : NSObject // Help the compiler +@end +#endif static Class abstractClass; @@ -75,6 +81,9 @@ @interface NSDataStatic : NSData // Help the compiler static Class rectValueClass; static Class sizeValueClass; static Class GSPlaceholderValueClass; +#if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) +static Class edgeInsetsValueClass; +#endif static GSPlaceholderValue *defaultPlaceholderValue; @@ -128,6 +137,9 @@ + (void) initialize rectValueClass = [GSRectValue class]; sizeValueClass = [GSSizeValue class]; GSPlaceholderValueClass = [GSPlaceholderValue class]; + #if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) + edgeInsetsValueClass = [GSEdgeInsetsValue class]; + #endif /* * Set up infrastructure for placeholder values. @@ -217,6 +229,10 @@ + (Class) valueClassWithObjCType: (const char *)type theClass = rectValueClass; else if (strcmp(@encode(NSSize), type) == 0) theClass = sizeValueClass; + #if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) + else if (strcmp(@encode(NSEdgeInsets), type) == 0) + theClass = edgeInsetsValueClass; + #endif /* Try for equivalent types match. */ @@ -232,6 +248,10 @@ + (Class) valueClassWithObjCType: (const char *)type theClass = rectValueClass; else if (GSSelectorTypesMatch(@encode(NSSize), type)) theClass = sizeValueClass; + #if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) + else if (GSSelectorTypesMatch(@encode(NSEdgeInsets), type)) + theClass = edgeInsetsValueClass; + #endif return theClass; } @@ -314,6 +334,17 @@ + (NSValue*) valueWithSize: (NSSize)size return AUTORELEASE(theObj); } +#if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) ++ (NSValue*) valueWithEdgeInsets: (NSEdgeInsets)insets +{ + NSValue *theObj; + + theObj = [edgeInsetsValueClass allocWithZone: NSDefaultMallocZone()]; + theObj = [theObj initWithBytes: &insets objCType: @encode(NSEdgeInsets)]; + return AUTORELEASE(theObj); +} +#endif + + (NSValue*) valueFromString: (NSString *)string { NSDictionary *dict = [string propertyList]; @@ -424,6 +455,14 @@ - (NSPoint) pointValue return NSMakePoint(0,0); } +#if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) +- (NSEdgeInsets) edgeInsetsValue +{ + [self subclassResponsibility: _cmd]; + return NSEdgeInsetsMake(0,0,0,0); +} +#endif + - (Class) classForCoder { return abstractClass; @@ -468,6 +507,15 @@ - (void) encodeWithCoder: (NSCoder *)coder [coder encodeValueOfObjCType: objctype at: &v]; return; } + #if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) + else if (strncmp(NSINSETS_ENCODING_PREFIX, objctype, strlen(NSINSETS_ENCODING_PREFIX)) == 0) + { + NSEdgeInsets v = [self edgeInsetsValue]; + + [coder encodeValueOfObjCType: objctype at: &v]; + return; + } + #endif NSGetSizeAndAlignment(objctype, &tsize, NULL); data = (void *)NSZoneMalloc([self zone], tsize); @@ -517,6 +565,10 @@ - (id) initWithCoder: (NSCoder *)coder c = [abstractClass valueClassWithObjCType: @encode(NSRect)]; else if (strncmp(NSRANGE_ENCODING_PREFIX, objctype, strlen(NSRANGE_ENCODING_PREFIX)) == 0) c = [abstractClass valueClassWithObjCType: @encode(NSRange)]; + #if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) + else if (strncmp(NSINSETS_ENCODING_PREFIX, objctype, strlen(NSINSETS_ENCODING_PREFIX)) == 0) + c = [abstractClass valueClassWithObjCType: @encode(NSEdgeInsets)]; + #endif else c = [abstractClass valueClassWithObjCType: objctype]; o = [c allocWithZone: [coder objectZone]]; @@ -556,6 +608,16 @@ - (id) initWithCoder: (NSCoder *)coder DESTROY(self); return [o initWithBytes: &v objCType: @encode(NSRect)]; } + #if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) + else if (c == edgeInsetsValueClass) + { + NSEdgeInsets v; + + [coder decodeValueOfObjCType: @encode(NSEdgeInsets) at: &v]; + DESTROY(self); + return [o initWithBytes: &v objCType: @encode(NSEdgeInsets)]; + } + #endif } if (ver < 2) @@ -590,6 +652,16 @@ - (id) initWithCoder: (NSCoder *)coder [coder decodeValueOfObjCType: @encode(NSRect) at: &v]; o = [o initWithBytes: &v objCType: @encode(NSRect)]; } + #if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST) + else if (c == edgeInsetsValueClass) + { + NSEdgeInsets v; + + [coder decodeValueOfObjCType: @encode(NSEdgeInsets) at: &v]; + o = [o initWithBytes: &v objCType: @encode(NSEdgeInsets)]; + } + + #endif else { unsigned char *data; diff --git a/Source/typeEncodingHelper.h b/Source/typeEncodingHelper.h index 3a24741ef..1c708649e 100644 --- a/Source/typeEncodingHelper.h +++ b/Source/typeEncodingHelper.h @@ -36,6 +36,7 @@ * @encoding(CGSize) -> {CGSize=dd} * @encoding(NSRange) -> {_NSRange=QQ} * @encoding(CFRange) -> {?=qq} +* @encoding(NSEdgeInsets) -> {NSEdgeInsets=dddd} * * Note that NSRange and CFRange are not toll-free bridged. * You cannot pass a CFRange to +[NSValue valueWithRange:] @@ -49,11 +50,13 @@ static const char *CGPOINT_ENCODING_PREFIX = "{CGPoint="; static const char *CGSIZE_ENCODING_PREFIX = "{CGSize="; static const char *CGRECT_ENCODING_PREFIX = "{CGRect="; +static const char *NSINSETS_ENCODING_PREFIX __attribute__((used)) = "{NSEdgeInsets="; static const char *NSRANGE_ENCODING_PREFIX = "{_NSRange="; #define IS_CGPOINT_ENCODING(encoding) (strncmp(encoding, CGPOINT_ENCODING_PREFIX, strlen(CGPOINT_ENCODING_PREFIX)) == 0) #define IS_CGSIZE_ENCODING(encoding) (strncmp(encoding, CGSIZE_ENCODING_PREFIX, strlen(CGSIZE_ENCODING_PREFIX)) == 0) #define IS_CGRECT_ENCODING(encoding) (strncmp(encoding, CGRECT_ENCODING_PREFIX, strlen(CGRECT_ENCODING_PREFIX)) == 0) +#define IS_NSINSETS_ENCODING(encoding) (strncmp(encoding, NSINSETS_ENCODING_PREFIX, strlen(NSINSETS_ENCODING_PREFIX)) == 0) #define IS_NSRANGE_ENCODING(encoding) (strncmp(encoding, NSRANGE_ENCODING_PREFIX, strlen(NSRANGE_ENCODING_PREFIX)) == 0) #endif /* __TYPE_ENCODING_HELPER_H */ diff --git a/Tests/base/KVC/type_encoding.m b/Tests/base/KVC/type_encoding.m index 2911705d1..3a0ff52f6 100644 --- a/Tests/base/KVC/type_encoding.m +++ b/Tests/base/KVC/type_encoding.m @@ -9,6 +9,7 @@ int main(int argc, char *argv[]) { PASS(strncmp(@encode(NSPoint), CGPOINT_ENCODING_PREFIX, strlen(CGPOINT_ENCODING_PREFIX)) == 0, "CGPoint encoding"); PASS(strncmp(@encode(NSSize), CGSIZE_ENCODING_PREFIX, strlen(CGSIZE_ENCODING_PREFIX)) == 0, "CGSize encoding"); PASS(strncmp(@encode(NSRect), CGRECT_ENCODING_PREFIX, strlen(CGRECT_ENCODING_PREFIX)) == 0, "CGRect encoding"); + PASS(strncmp(@encode(NSEdgeInsets), NSINSETS_ENCODING_PREFIX, strlen(NSINSETS_ENCODING_PREFIX)) == 0, "NSEdgeInsets encoding"); PASS(strncmp(@encode(NSRange), NSRANGE_ENCODING_PREFIX, strlen(NSRANGE_ENCODING_PREFIX)) == 0, "NSRange encoding"); END_SET("Known Struct Type Encodings")