Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -170,13 +170,16 @@ OFMutableSet_hashtable.m \ OFMutableString_UTF8.m \ OFSet_hashtable.m \ OFString_UTF8.m \ OFValue_bytes.m \ + OFValue_dimension.m \ OFValue_nonretainedObject.m \ + OFValue_point.m \ OFValue_pointer.m \ OFValue_range.m \ + OFValue_rectangle.m \ ${AUTORELEASE_M} \ ${FOUNDATION_COMPAT_M} \ ${INSTANCE_M} SRCS_FILES += OFSettings_INIFile.m \ OFURLHandler_file.m Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -95,10 +95,29 @@ { of_range_t range = { start, length }; return range; } + +/*! + * @brief Returns whether the two ranges are equal. + * + * @param range1 The first range for the comparison + * @param range2 The second range for the comparison + * @return Whether the two ranges are equal + */ +static OF_INLINE bool +of_range_equal(of_range_t range1, of_range_t range2) +{ + if (range1.location != range2.location) + return false; + + if (range1.length != range2.length) + return false; + + return true; +} /*! * @brief A time interval in seconds. */ typedef double of_time_interval_t; @@ -127,10 +146,29 @@ { of_point_t point = { x, y }; return point; } + +/*! + * @brief Returns whether the two points are equal. + * + * @param point1 The first point for the comparison + * @param point2 The second point for the comparison + * @return Whether the two points are equal + */ +static OF_INLINE bool +of_point_equal(of_point_t point1, of_point_t point2) +{ + if (point1.x != point2.x) + return false; + + if (point1.y != point2.y) + return false; + + return true; +} /*! * @struct of_dimension_t OFObject.h ObjFW/OFObject.h * * @brief A dimension. @@ -154,10 +192,29 @@ { of_dimension_t dimension = { width, height }; return dimension; } + +/*! + * @brief Returns whether the two dimensions are equal. + * + * @param dimension1 The first dimension for the comparison + * @param dimension2 The second dimension for the comparison + * @return Whether the two dimensions are equal + */ +static OF_INLINE bool +of_dimension_equal(of_dimension_t dimension1, of_dimension_t dimension2) +{ + if (dimension1.width != dimension2.width) + return false; + + if (dimension1.height != dimension2.height) + return false; + + return true; +} /*! * @struct of_rectangle_t OFObject.h ObjFW/OFObject.h * * @brief A rectangle. @@ -186,10 +243,29 @@ of_dimension(width, height) }; return rectangle; } + +/*! + * @brief Returns whether the two rectangles are equal. + * + * @param rectangle1 The first rectangle for the comparison + * @param rectangle2 The second rectangle for the comparison + * @return Whether the two rectangles are equal + */ +static OF_INLINE bool +of_rectangle_equal(of_rectangle_t rectangle1, of_rectangle_t rectangle2) +{ + if (!of_point_equal(rectangle1.origin, rectangle2.origin)) + return false; + + if (!of_dimension_equal(rectangle1.size, rectangle2.size)) + return false; + + return true; +} @class OFMethodSignature; @class OFString; @class OFThread; Index: src/OFValue.h ================================================================== --- src/OFValue.h +++ src/OFValue.h @@ -49,10 +49,31 @@ * * If the value is not range-sized, @ref OFOutOfRangeException is thrown. */ @property (readonly, nonatomic) of_range_t rangeValue; +/*! + * @brief The value as a point. + * + * If the value is not point-sized, @ref OFOutOfRangeException is thrown. + */ +@property (readonly, nonatomic) of_point_t pointValue; + +/*! + * @brief The value as a dimension. + * + * If the value is not dimension-sized, @ref OFOutOfRangeException is thrown. + */ +@property (readonly, nonatomic) of_dimension_t dimensionValue; + +/*! + * @brief The value as a rectangle. + * + * If the value is not rectangle-sized, @ref OFOutOfRangeException is thrown. + */ +@property (readonly, nonatomic) of_rectangle_t rectangleValue; + /*! * @brief Creates a new, autorelease OFValue with the specified bytes of the * specified type. * * @param bytes The bytes containing the value @@ -90,10 +111,36 @@ * @param range The range the OFValue should contain * @return A new, autoreleased OFValue */ + (instancetype)valueWithRange: (of_range_t)range; +/*! + * @brief Creates a new, autoreleased OFValue containing the specified point. + * + * @param point The point the OFValue should contain + * @return A new, autoreleased OFValue + */ ++ (instancetype)valueWithPoint: (of_point_t)point; + +/*! + * @brief Creates a new, autoreleased OFValue containing the specified + * dimension. + * + * @param dimension The dimension the OFValue should contain + * @return A new, autoreleased OFValue + */ ++ (instancetype)valueWithDimension: (of_dimension_t)dimension; + +/*! + * @brief Creates a new, autoreleased OFValue containing the specified + * rectangle. + * + * @param rectangle The rectangle the OFValue should contain + * @return A new, autoreleased OFValue + */ ++ (instancetype)valueWithRectangle: (of_rectangle_t)rectangle; + /*! * @brief Initializes an already allocated OFValue with the specified bytes of * the specified type. * * @param bytes The bytes containing the value @@ -133,10 +180,37 @@ * @param range The range the OFValue should contain * @return An initialized OFValue */ - (instancetype)initWithRange: (of_range_t)range; +/*! + * @brief Initializes an already allocated OFValue containing the specified + * point. + * + * @param point The point the OFValue should contain + * @return An initialized OFValue + */ +- (instancetype)initWithPoint: (of_point_t)point; + +/*! + * @brief Initializes an already allocated OFValue containing the specified + * dimension. + * + * @param dimension The dimension the OFValue should contain + * @return An initialized OFValue + */ +- (instancetype)initWithDimension: (of_dimension_t)dimension; + +/*! + * @brief Initializes an already allocated OFValue containing the specified + * rectangle. + * + * @param rectangle The rectangle the OFValue should contain + * @return An initialized OFValue + */ +- (instancetype)initWithRectangle: (of_rectangle_t)rectangle; + /*! * @brief Gets the value. * * If the specified size does not match, this raises an * @ref OFOutOfRangeException. Index: src/OFValue.m ================================================================== --- src/OFValue.m +++ src/OFValue.m @@ -17,13 +17,16 @@ #import "OFValue.h" #import "OFMethodSignature.h" #import "OFString.h" #import "OFValue_bytes.h" +#import "OFValue_dimension.h" #import "OFValue_nonretainedObject.h" +#import "OFValue_point.h" #import "OFValue_pointer.h" #import "OFValue_range.h" +#import "OFValue_rectangle.h" #import "OFOutOfMemoryException.h" static struct { Class isa; @@ -53,10 +56,25 @@ - (instancetype)initWithRange: (of_range_t)range { return (id)[[OFValue_range alloc] initWithRange: range]; } + +- (instancetype)initWithPoint: (of_point_t)point +{ + return (id)[[OFValue_point alloc] initWithPoint: point]; +} + +- (instancetype)initWithDimension: (of_dimension_t)dimension +{ + return (id)[[OFValue_dimension alloc] initWithDimension: dimension]; +} + +- (instancetype)initWithRectangle: (of_rectangle_t)rectangle +{ + return (id)[[OFValue_rectangle alloc] initWithRectangle: rectangle]; +} @end @implementation OFValue + (void)initialize { @@ -91,10 +109,25 @@ + (instancetype)valueWithRange: (of_range_t)range { return [[[self alloc] initWithRange: range] autorelease]; } + ++ (instancetype)valueWithPoint: (of_point_t)point +{ + return [[[self alloc] initWithPoint: point] autorelease]; +} + ++ (instancetype)valueWithDimension: (of_dimension_t)dimension +{ + return [[[self alloc] initWithDimension: dimension] autorelease]; +} + ++ (instancetype)valueWithRectangle: (of_rectangle_t)rectangle +{ + return [[[self alloc] initWithRectangle: rectangle] autorelease]; +} - (instancetype)initWithBytes: (const void *)bytes objCType: (const char *)objCType { OF_INVALID_INIT_METHOD @@ -110,10 +143,25 @@ OF_INVALID_INIT_METHOD } - (instancetype)initWithRange: (of_range_t)range { + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithPoint: (of_point_t)point +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithDimension: (of_dimension_t)dimension +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithRectangle: (of_rectangle_t)rectangle +{ OF_INVALID_INIT_METHOD } - (bool)isEqual: (id)object { @@ -218,10 +266,40 @@ } - (of_range_t)rangeValue { of_range_t ret; + + [self getValue: &ret + size: sizeof(ret)]; + + return ret; +} + +- (of_point_t)pointValue +{ + of_point_t ret; + + [self getValue: &ret + size: sizeof(ret)]; + + return ret; +} + +- (of_dimension_t)dimensionValue +{ + of_dimension_t ret; + + [self getValue: &ret + size: sizeof(ret)]; + + return ret; +} + +- (of_rectangle_t)rectangleValue +{ + of_rectangle_t ret; [self getValue: &ret size: sizeof(ret)]; return ret; ADDED src/OFValue_dimension.h Index: src/OFValue_dimension.h ================================================================== --- src/OFValue_dimension.h +++ src/OFValue_dimension.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFValue.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFValue_dimension: OFValue +{ + of_dimension_t _dimension; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFValue_dimension.m Index: src/OFValue_dimension.m ================================================================== --- src/OFValue_dimension.m +++ src/OFValue_dimension.m @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFValue_dimension.h" +#import "OFMethodSignature.h" +#import "OFString.h" + +#import "OFOutOfRangeException.h" + +@implementation OFValue_dimension +@synthesize dimensionValue = _dimension; + +- (instancetype)initWithDimension: (of_dimension_t)dimension +{ + self = [super init]; + + _dimension = dimension; + + return self; +} + +- (const char *)objCType +{ + return @encode(of_dimension_t); +} + +- (void)getValue: (void *)value + size: (size_t)size +{ + if (size != sizeof(_dimension)) + @throw [OFOutOfRangeException exception]; + + memcpy(value, &_dimension, sizeof(_dimension)); +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"", + _dimension.width, _dimension.height]; +} +@end Index: src/OFValue_nonretainedObject.m ================================================================== --- src/OFValue_nonretainedObject.m +++ src/OFValue_nonretainedObject.m @@ -29,10 +29,15 @@ _object = object; return self; } + +- (const char *)objCType +{ + return @encode(id); +} - (void)getValue: (void *)value size: (size_t)size { if (size != sizeof(_object)) ADDED src/OFValue_point.h Index: src/OFValue_point.h ================================================================== --- src/OFValue_point.h +++ src/OFValue_point.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFValue.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFValue_point: OFValue +{ + of_point_t _point; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFValue_point.m Index: src/OFValue_point.m ================================================================== --- src/OFValue_point.m +++ src/OFValue_point.m @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFValue_point.h" +#import "OFMethodSignature.h" +#import "OFString.h" + +#import "OFOutOfRangeException.h" + +@implementation OFValue_point +@synthesize pointValue = _point; + +- (instancetype)initWithPoint: (of_point_t)point +{ + self = [super init]; + + _point = point; + + return self; +} + +- (const char *)objCType +{ + return @encode(of_point_t); +} + +- (void)getValue: (void *)value + size: (size_t)size +{ + if (size != sizeof(_point)) + @throw [OFOutOfRangeException exception]; + + memcpy(value, &_point, sizeof(_point)); +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"", _point.x, _point.y]; +} +@end Index: src/OFValue_pointer.m ================================================================== --- src/OFValue_pointer.m +++ src/OFValue_pointer.m @@ -29,10 +29,15 @@ _pointer = (void *)pointer; return self; } + +- (const char *)objCType +{ + return @encode(void *); +} - (void)getValue: (void *)value size: (size_t)size { if (size != sizeof(_pointer)) Index: src/OFValue_range.m ================================================================== --- src/OFValue_range.m +++ src/OFValue_range.m @@ -30,10 +30,15 @@ _range = range; return self; } + +- (const char *)objCType +{ + return @encode(of_range_t); +} - (void)getValue: (void *)value size: (size_t)size { if (size != sizeof(_range)) @@ -42,9 +47,10 @@ memcpy(value, &_range, sizeof(_range)); } - (OFString *)description { - return [OFString stringWithFormat: @"", - _range.location, _range.length]; + return [OFString stringWithFormat: + @"", + _range.location, _range.length]; } @end ADDED src/OFValue_rectangle.h Index: src/OFValue_rectangle.h ================================================================== --- src/OFValue_rectangle.h +++ src/OFValue_rectangle.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFValue.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFValue_rectangle: OFValue +{ + of_rectangle_t _rectangle; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFValue_rectangle.m Index: src/OFValue_rectangle.m ================================================================== --- src/OFValue_rectangle.m +++ src/OFValue_rectangle.m @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFValue_rectangle.h" +#import "OFMethodSignature.h" +#import "OFString.h" + +#import "OFOutOfRangeException.h" + +@implementation OFValue_rectangle +@synthesize rectangleValue = _rectangle; + +- (instancetype)initWithRectangle: (of_rectangle_t)rectangle +{ + self = [super init]; + + _rectangle = rectangle; + + return self; +} + +- (const char *)objCType +{ + return @encode(of_rectangle_t); +} + +- (void)getValue: (void *)value + size: (size_t)size +{ + if (size != sizeof(_rectangle)) + @throw [OFOutOfRangeException exception]; + + memcpy(value, &_rectangle, sizeof(_rectangle)); +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"", + _rectangle.origin.x, _rectangle.origin.y, + _rectangle.size.width, _rectangle.size.height]; +} +@end Index: tests/OFValueTests.m ================================================================== --- tests/OFValueTests.m +++ tests/OFValueTests.m @@ -30,25 +30,27 @@ @implementation TestsAppDelegate (OFValueTests) - (void)valueTests { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - of_range_t range = of_range(1, 64), range2 = of_range(1, 64); + of_range_t range = of_range(1, 64), range2; + of_point_t point = of_point(1.5, 3), point2; + of_dimension_t dimension = of_dimension(4.5, 5), dimension2; + of_rectangle_t rectangle = of_rectangle(1.5, 3, 4.5, 6), rectangle2; OFValue *value; void *pointer = &value; TEST(@"+[valueWithBytes:objCType:]", (value = [OFValue valueWithBytes: &range objCType: @encode(of_range_t)])) TEST(@"-[objCType]", strcmp([value objCType], @encode(of_range_t)) == 0) - range = of_range(OF_NOT_FOUND, 0); TEST(@"-[getValue:size:]", - R([value getValue: &range + R([value getValue: &range2 size: sizeof(of_range_t)]) && - memcmp(&range, &range2, sizeof(of_range_t)) == 0) + of_range_equal(range2, range)) EXPECT_EXCEPTION(@"-[getValue:size:] with wrong size throws", OFOutOfRangeException, [value getValue: &range size: sizeof(of_range_t) - 1]) @@ -81,19 +83,84 @@ TEST(@"+[valueWithRange:]", (value = [OFValue valueWithRange: range])) TEST(@"-[rangeValue]", - R(range = [value rangeValue]) && - memcmp(&range, &range2, sizeof(of_range_t)) == 0 && R(range = - [[OFValue valueWithBytes: &range - objCType: @encode(of_range_t)] rangeValue]) && - memcmp(&range, &range2, sizeof(of_range_t)) == 0) + of_range_equal([value rangeValue], range) && + (value = [OFValue valueWithBytes: &range + objCType: @encode(of_range_t)]) && + of_range_equal([value rangeValue], range)) + + TEST(@"-[getValue:size:] for OFValue_range", + (value = [OFValue valueWithRange: range]) && + R([value getValue: &range2 + size: sizeof(range2)]) && + of_range_equal(range2, range)) EXPECT_EXCEPTION(@"-[rangeValue] with wrong size throws", OFOutOfRangeException, [[OFValue valueWithBytes: "a" objCType: @encode(char)] rangeValue]) + TEST(@"+[valueWithPoint:]", + (value = [OFValue valueWithPoint: point])) + + TEST(@"-[pointValue]", + of_point_equal([value pointValue], point) && + (value = [OFValue valueWithBytes: &point + objCType: @encode(of_point_t)]) && + of_point_equal([value pointValue], point)) + + TEST(@"-[getValue:size:] for OFValue_point", + (value = [OFValue valueWithPoint: point]) && + R([value getValue: &point2 + size: sizeof(point2)]) && + of_point_equal(point2, point)) + + EXPECT_EXCEPTION(@"-[pointValue] with wrong size throws", + OFOutOfRangeException, + [[OFValue valueWithBytes: "a" + objCType: @encode(char)] pointValue]) + + TEST(@"+[valueWithDimension:]", + (value = [OFValue valueWithDimension: dimension])) + + TEST(@"-[dimensionValue]", + of_dimension_equal([value dimensionValue], dimension) && + (value = [OFValue valueWithBytes: &dimension + objCType: @encode(of_dimension_t)]) && + of_dimension_equal([value dimensionValue], dimension)) + + TEST(@"-[getValue:size:] for OFValue_dimension", + (value = [OFValue valueWithDimension: dimension]) && + R([value getValue: &dimension2 + size: sizeof(dimension2)]) && + of_dimension_equal(dimension2, dimension)) + + EXPECT_EXCEPTION(@"-[dimensionValue] with wrong size throws", + OFOutOfRangeException, + [[OFValue valueWithBytes: "a" + objCType: @encode(char)] dimensionValue]) + + TEST(@"+[valueWithRectangle:]", + (value = [OFValue valueWithRectangle: rectangle])) + + TEST(@"-[rectangleValue]", + of_rectangle_equal([value rectangleValue], rectangle) && + (value = [OFValue valueWithBytes: &rectangle + objCType: @encode(of_rectangle_t)]) && + of_rectangle_equal([value rectangleValue], rectangle)) + + TEST(@"-[getValue:size:] for OFValue_rectangle", + (value = [OFValue valueWithRectangle: rectangle]) && + R([value getValue: &rectangle2 + size: sizeof(rectangle2)]) && + of_rectangle_equal(rectangle2, rectangle)) + + EXPECT_EXCEPTION(@"-[rectangleValue] with wrong size throws", + OFOutOfRangeException, + [[OFValue valueWithBytes: "a" + objCType: @encode(char)] rectangleValue]) + [pool drain]; } @end