/*
* Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
*
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3.0 only,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* version 3.0 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3.0 along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "objfw-defs.h"
#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
#endif
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include "macros.h"
#import "OFOnce.h"
/*
* Some versions of MinGW require <winsock2.h> to be included before
* <windows.h>. Do this here to make sure this is always done in the correct
* order, even if another header includes just <windows.h>.
*/
#ifdef __MINGW32__
# include <_mingw.h>
# ifdef __MINGW64_VERSION_MAJOR
# include <winsock2.h>
# include <windows.h>
# endif
#endif
OF_ASSUME_NONNULL_BEGIN
/** @file */
/**
* @brief A result of a comparison.
*/
typedef enum {
/** The left object is smaller than the right */
OFOrderedAscending = -1,
/** Both objects are equal */
OFOrderedSame = 0,
/** The left object is bigger than the right */
OFOrderedDescending = 1
} OFComparisonResult;
/**
* @brief A function to compare two objects.
*
* @param left The left object
* @param right The right object
* @param context Context passed along for comparing
* @return The order of the objects
*/
typedef OFComparisonResult (*OFCompareFunction)(id _Nonnull left,
id _Nonnull right, void *_Nullable context);
#ifdef OF_HAVE_BLOCKS
/**
* @brief A comparator to compare two objects.
*
* @param left The left object
* @param right The right object
* @return The order of the objects
*/
typedef OFComparisonResult (^OFComparator)(id _Nonnull left, id _Nonnull right);
#endif
/**
* @brief An enum for representing endianness.
*/
typedef enum {
/** Most significant byte first (big endian) */
OFByteOrderBigEndian,
/** Least significant byte first (little endian) */
OFByteOrderLittleEndian,
/** Native byte order of the system */
#ifdef OF_BIG_ENDIAN
OFByteOrderNative = OFByteOrderBigEndian
#else
OFByteOrderNative = OFByteOrderLittleEndian
#endif
} OFByteOrder;
/**
* @struct OFRange OFObject.h ObjFW/ObjFW.h
*
* @brief A range.
*/
typedef struct OF_BOXABLE OFRange {
/** The start of the range */
size_t location;
/** The length of the range */
size_t length;
} OFRange;
/**
* @brief Creates a new OFRange.
*
* @param start The starting index of the range
* @param length The length of the range
* @return An OFRange with the specified start and length
*/
static OF_INLINE OFRange OF_CONST_FUNC
OFMakeRange(size_t start, size_t length)
{
OFRange 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
OFEqualRanges(OFRange range1, OFRange 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 OFTimeInterval;
/**
* @struct OFPoint OFObject.h ObjFW/ObjFW.h
*
* @brief A point in 2D space.
*/
typedef struct OF_BOXABLE OFPoint {
/** The x coordinate of the point */
float x;
/** The y coordinate of the point */
float y;
} OFPoint;
/**
* @brief Creates a new OFPoint.
*
* @param x The x coordinate of the point
* @param y The x coordinate of the point
* @return An OFPoint with the specified coordinates
*/
static OF_INLINE OFPoint OF_CONST_FUNC
OFMakePoint(float x, float y)
{
OFPoint 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
OFEqualPoints(OFPoint point1, OFPoint point2)
{
if (point1.x != point2.x)
return false;
if (point1.y != point2.y)
return false;
return true;
}
/**
* @struct OFSize OFObject.h ObjFW/ObjFW.h
*
* @brief A size.
*/
typedef struct OF_BOXABLE OFSize {
/** The width of the size */
float width;
/** The height of the size */
float height;
} OFSize;
/**
* @brief Creates a new OFSize.
*
* @param width The width of the size
* @param height The height of the size
* @return An OFSize with the specified width and height
*/
static OF_INLINE OFSize OF_CONST_FUNC
OFMakeSize(float width, float height)
{
OFSize size = { width, height };
return size;
}
/**
* @brief Returns whether the two sizes are equal.
*
* @param size1 The first size for the comparison
* @param size2 The second size for the comparison
* @return Whether the two sizes are equal
*/
static OF_INLINE bool
OFEqualSizes(OFSize size1, OFSize size2)
{
if (size1.width != size2.width)
return false;
if (size1.height != size2.height)
return false;
return true;
}
/**
* @struct OFRect OFObject.h ObjFW/ObjFW.h
*
* @brief A rectangle.
*/
typedef struct OF_BOXABLE OFRect {
/** The point from where the rectangle originates */
OFPoint origin;
/** The size of the rectangle */
OFSize size;
} OFRect;
/**
* @brief Creates a new OFRect.
*
* @param x The x coordinate of the top left corner of the rectangle
* @param y The y coordinate of the top left corner of the rectangle
* @param width The width of the rectangle
* @param height The height of the rectangle
* @return An OFRect with the specified origin and size
*/
static OF_INLINE OFRect OF_CONST_FUNC
OFMakeRect(float x, float y, float width, float height)
{
OFRect rect = {
OFMakePoint(x, y),
OFMakeSize(width, height)
};
return rect;
}
/**
* @brief Returns whether the two rectangles are equal.
*
* @param rect1 The first rectangle for the comparison
* @param rect2 The second rectangle for the comparison
* @return Whether the two rectangles are equal
*/
static OF_INLINE bool
OFEqualRects(OFRect rect1, OFRect rect2)
{
if (!OFEqualPoints(rect1.origin, rect2.origin))
return false;
if (!OFEqualSizes(rect1.size, rect2.size))
return false;
return true;
}
/**
* @struct OFVector3D OFObject.h ObjFW/ObjFW.h
*
* @brief A vector in 3D space.
*/
typedef struct OF_BOXABLE OFVector3D {
/** The x coordinate of the vector */
float x;
/** The y coordinate of the vector */
float y;
/** The z coordinate of the vector */
float z;
} OFVector3D;
/**
* @brief Creates a new OFVector3D.
*
* @param x The x coordinate of the vector
* @param y The x coordinate of the vector
* @param z The z coordinate of the vector
* @return An OFVector3D with the specified coordinates
*/
static OF_INLINE OFVector3D OF_CONST_FUNC
OFMakeVector3D(float x, float y, float z)
{
OFVector3D vector = { x, y, z };
return vector;
}
/**
* @brief Returns whether the two vectors are equal.
*
* @param vector1 The first vector for the comparison
* @param vector2 The second vectors for the comparison
* @return Whether the two vectors are equal
*/
static OF_INLINE bool
OFEqualVectors3D(OFVector3D vector1, OFVector3D vector2)
{
if (vector1.x != vector2.x)
return false;
if (vector1.y != vector2.y)
return false;
if (vector1.z != vector2.z)
return false;
return true;
}
/**
* @struct OFVector4D OFObject.h ObjFW/ObjFW.h
*
* @brief A vector in 4D space.
*/
typedef struct OF_BOXABLE OFVector4D {
/** The x coordinate of the vector */
float x;
/** The y coordinate of the vector */
float y;
/** The z coordinate of the vector */
float z;
/** The w coordinate of the vector */
float w;
} OFVector4D;
/**
* @brief Creates a new OFVector4D.
*
* @param x The x coordinate of the vector
* @param y The x coordinate of the vector
* @param z The z coordinate of the vector
* @param w The w coordinate of the vector
* @return An OFVector4D with the specified coordinates
*/
static OF_INLINE OFVector4D OF_CONST_FUNC
OFMakeVector4D(float x, float y, float z, float w)
{
OFVector4D vector = { x, y, z, w };
return vector;
}
/**
* @brief Returns whether the two vectors are equal.
*
* @param vector1 The first vector for the comparison
* @param vector2 The second vectors for the comparison
* @return Whether the two vectors are equal
*/
static OF_INLINE bool
OFEqualVectors4D(OFVector4D vector1, OFVector4D vector2)
{
if (vector1.x != vector2.x)
return false;
if (vector1.y != vector2.y)
return false;
if (vector1.z != vector2.z)
return false;
if (vector1.w != vector2.w)
return false;
return true;
}
/**
* @brief Adds the specified byte to the hash.
*
* @param hash A pointer to a hash to add the byte to
* @param byte The byte to add to the hash
*/
static OF_INLINE void
OFHashAddByte(unsigned long *_Nonnull hash, unsigned char byte)
{
uint32_t tmp = (uint32_t)*hash;
tmp += byte;
tmp += tmp << 10;
tmp ^= tmp >> 6;
*hash = tmp;
}
/**
* @brief Adds the specified hash to the hash.
*
* @param hash A pointer to a hash to add the hash to
* @param otherHash The hash to add to the hash
*/
static OF_INLINE void
OFHashAddHash(unsigned long *_Nonnull hash, unsigned long otherHash)
{
OFHashAddByte(hash, (otherHash >> 24) & 0xFF);
OFHashAddByte(hash, (otherHash >> 16) & 0xFF);
OFHashAddByte(hash, (otherHash >> 8) & 0xFF);
OFHashAddByte(hash, otherHash & 0xFF);
}
/**
* @brief Finalizes the specified hash.
*
* @param hash A pointer to the hash to finalize
*/
static OF_INLINE void
OFHashFinalize(unsigned long *_Nonnull hash)
{
uint32_t tmp = (uint32_t)*hash;
tmp += tmp << 3;
tmp ^= tmp >> 11;
tmp += tmp << 15;
*hash = tmp;
}
static const size_t OFNotFound = SIZE_MAX;
@class OFMethodSignature;
@class OFString;
@class OFThread;
/**
* @protocol OFObject OFObject.h ObjFW/ObjFW.h
*
* @brief The protocol which all root classes implement.
*/
@protocol OFObject
/**
* @brief Returns the class of the object.
*
* @return The class of the object
*/
- (Class)class;
/**
* @brief Returns the superclass of the object.
*
* @return The superclass of the object
*/
- (nullable Class)superclass;
/**
* @brief Returns a hash for the object.
*
* Classes containing data (like strings, arrays, lists etc.) should reimplement
* this!
*
* @warning If you reimplement this, you also need to reimplement @ref isEqual:
* to behave in a way compatible to your reimplementation of this
* method!
*
* @return A hash for the object
*/
- (unsigned long)hash;
/**
* @brief Returns the retain count.
*
* @return The retain count
*/
- (unsigned int)retainCount;
/**
* @brief Returns whether the object is a proxy object.
*
* @return Whether the object is a proxy object
*/
- (bool)isProxy;
/**
* @brief Returns a boolean whether the object is of the specified kind.
*
* @param class_ The class for which the receiver is checked
* @return A boolean whether the object is of the specified kind
*/
- (bool)isKindOfClass: (Class)class_;
/**
* @brief Returns a boolean whether the object is a member of the specified
* class.
*
* @param class_ The class for which the receiver is checked
* @return A boolean whether the object is a member of the specified class
*/
- (bool)isMemberOfClass: (Class)class_;
/**
* @brief Returns a boolean whether the object responds to the specified
* selector.
*
* @param selector The selector which should be checked for respondence
* @return A boolean whether the objects responds to the specified selector
*/
- (bool)respondsToSelector: (SEL)selector;
/**
* @brief Checks whether the object conforms to the specified protocol.
*
* @param protocol The protocol which should be checked for conformance
* @return A boolean whether the object conforms to the specified protocol
*/
- (bool)conformsToProtocol: (Protocol *)protocol;
/**
* @brief Returns the implementation for the specified selector.
*
* @param selector The selector for which the method should be returned
* @return The implementation for the specified selector
*/
- (nullable IMP)methodForSelector: (SEL)selector;
/**
* @brief Performs the specified selector.
*
* @param selector The selector to perform
* @return The object returned by the method specified by the selector
*/
- (nullable id)performSelector: (SEL)selector;
/**
* @brief Performs the specified selector with the specified object.
*
* @param selector The selector to perform
* @param object The object that is passed to the method specified by the
* selector
* @return The object returned by the method specified by the selector
*/
- (nullable id)performSelector: (SEL)selector withObject: (nullable id)object;
/**
* @brief Performs the specified selector with the specified objects.
*
* @param selector The selector to perform
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @return The object returned by the method specified by the selector
*/
- (nullable id)performSelector: (SEL)selector
withObject: (nullable id)object1
withObject: (nullable id)object2;
/**
* @brief Performs the specified selector with the specified objects.
*
* @param selector The selector to perform
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param object3 The third object that is passed to the method specified by the
* selector
* @return The object returned by the method specified by the selector
*/
- (nullable id)performSelector: (SEL)selector
withObject: (nullable id)object1
withObject: (nullable id)object2
withObject: (nullable id)object3;
/**
* @brief Performs the specified selector with the specified objects.
*
* @param selector The selector to perform
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param object3 The third object that is passed to the method specified by the
* selector
* @param object4 The fourth object that is passed to the method specified by
* the selector
* @return The object returned by the method specified by the selector
*/
- (nullable id)performSelector: (SEL)selector
withObject: (nullable id)object1
withObject: (nullable id)object2
withObject: (nullable id)object3
withObject: (nullable id)object4;
/**
* @brief Checks two objects for equality.
*
* Classes containing data (like strings, arrays, lists etc.) should reimplement
* this!
*
* @warning If you reimplement this, you also need to reimplement @ref hash to
* return the same hash for objects which are equal!
*
* @param object The object which should be tested for equality
* @return A boolean whether the object is equal to the specified object
*/
- (bool)isEqual: (nullable id)object;
/**
* @brief Increases the retain count.
*
* Each time an object is released, the retain count gets decreased and the
* object deallocated if it reaches 0.
*/
- (instancetype)retain;
/**
* @brief Decreases the retain count.
*
* Each time an object is released, the retain count gets decreased and the
* object deallocated if it reaches 0.
*/
- (void)release;
/**
* @brief Adds the object to the topmost autorelease pool of the thread's
* autorelease pool stack.
*
* @return The object
*/
- (instancetype)autorelease;
/**
* @brief Returns the receiver.
*
* @return The receiver
*/
- (instancetype)self;
/**
* @brief Returns whether the object allows a weak reference.
*
* @return Whether the object allows a weak references
*/
- (bool)allowsWeakReference;
/**
* @brief Retain a weak reference to this object.
*
* @return Whether a weak reference to this object has been retained
*/
- (bool)retainWeakReference;
@end
/**
* @class OFObject OFObject.h ObjFW/ObjFW.h
*
* @brief The root class for all other classes inside ObjFW.
*/
OF_ROOT_CLASS
@interface OFObject <OFObject>
{
@private
#ifndef __clang_analyzer__
Class _isa;
#else
Class _isa __attribute__((__unused__));
#endif
}
#ifdef OF_HAVE_CLASS_PROPERTIES
# ifndef __cplusplus
@property (class, readonly, nonatomic) Class class;
# else
@property (class, readonly, nonatomic, getter=class) Class class_;
# endif
@property (class, readonly, nonatomic) OFString *className;
@property (class, readonly, nullable, nonatomic) Class superclass;
@property (class, readonly, nonatomic) OFString *description;
#endif
#ifndef __cplusplus
@property (readonly, nonatomic) Class class;
#else
@property (readonly, nonatomic, getter=class) Class class_;
#endif
@property OF_NULLABLE_PROPERTY (readonly, nonatomic) Class superclass;
@property (readonly, nonatomic) unsigned long hash;
@property (readonly, nonatomic) unsigned int retainCount;
@property (readonly, nonatomic) bool isProxy;
@property (readonly, nonatomic) bool allowsWeakReference;
/**
* @brief The name of the object's class.
*/
@property (readonly, nonatomic) OFString *className;
/**
* @brief A description for the object.
*
* This is used when the object is used in a format string and for debugging
* purposes.
*/
@property (readonly, nonatomic) OFString *description;
/**
* @brief A method which is called once when the class is loaded into the
* runtime.
*
* Derived classes can override this to execute their own code when the class
* is loaded.
*/
+ (void)load;
/**
* @brief A method which is called when the class is unloaded from the runtime.
*
* Derived classes can override this to execute their own code when the class
* is unloaded.
*
* @warning This is not supported by the Apple runtime and currently only
* called by the ObjFW runtime when @ref objc_deinit has been called!
* In the future, this might also be called by the ObjFW runtime when
* the class is part of a plugin that is being unloaded.
*/
+ (void)unload;
/**
* @brief A method which is called the moment before the first call to the class
* is being made.
*
* Derived classes can override this to execute their own code on
* initialization. They should make sure to not execute any code if self is not
* the class itself, as it might happen that the method was called for a
* subclass which did not override this method.
*/
+ (void)initialize;
/**
* @brief Allocates memory for an instance of the class and sets up the memory
* pool for the object.
*
* This method will never return `nil`.
*
* @return The allocated object
* @throw OFAllocFailedException There was not enough memory to allocate the
* object
* @throw OFInitializationFailedException The instance could not be constructed
*/
+ (instancetype)alloc;
/**
* @brief Returns the class.
*
* @return The class
*/
+ (Class)class;
/**
* @brief Returns the name of the class as a string.
*
* @return The name of the class as a string
*/
+ (OFString *)className;
/**
* @brief Returns a boolean whether the class is a subclass of the specified
* class.
*
* @param class_ The class which is checked for being a superclass
* @return A boolean whether the class is a subclass of the specified class
*/
+ (bool)isSubclassOfClass: (Class)class_;
/**
* @brief Returns the superclass of the class.
*
* @return The superclass of the class
*/
+ (nullable Class)superclass;
/**
* @brief Checks whether instances of the class respond to a given selector.
*
* @param selector The selector which should be checked for respondence
* @return A boolean whether instances of the class respond to the specified
* selector
*/
+ (bool)instancesRespondToSelector: (SEL)selector;
/**
* @brief Checks whether the class conforms to a given protocol.
*
* @param protocol The protocol which should be checked for conformance
* @return A boolean whether the class conforms to the specified protocol
*/
+ (bool)conformsToProtocol: (Protocol *)protocol;
/**
* @brief Returns the implementation of the instance method for the specified
* selector.
*
* @param selector The selector for which the method should be returned
* @return The implementation of the instance method for the specified selector
* or `nil` if it isn't implemented
*/
+ (nullable IMP)instanceMethodForSelector: (SEL)selector;
/**
* @brief Returns the method signature of the instance method for the specified
* selector.
*
* @param selector The selector for which the method signature should be
* returned
* @return The method signature of the instance method for the specified
* selector
*/
+ (nullable OFMethodSignature *)
instanceMethodSignatureForSelector: (SEL)selector;
/**
* @brief Returns a description for the class, which is usually the class name.
*
* This is mostly for debugging purposes.
*
* @return A description for the class, which is usually the class name
*/
+ (OFString *)description;
/**
* @brief Replaces a class method with a class method from another class.
*
* @param selector The selector of the class method to replace
* @param class_ The class from which the new class method should be taken
* @return The old implementation
*/
+ (nullable IMP)replaceClassMethod: (SEL)selector
withMethodFromClass: (Class)class_;
/**
* @brief Replaces an instance method with an instance method from another
* class.
*
* @param selector The selector of the instance method to replace
* @param class_ The class from which the new instance method should be taken
* @return The old implementation
*/
+ (nullable IMP)replaceInstanceMethod: (SEL)selector
withMethodFromClass: (Class)class_;
/**
* @brief Adds all methods from the specified class to the class that is the
* receiver.
*
* Methods implemented by the receiving class itself will not be overridden,
* however methods implemented by its superclass will. Therefore it behaves
* similar as if the specified class is the superclass of the receiver.
*
* All methods from the superclasses of the specified class will also be added.
*
* If the specified class is a superclass of the receiving class, nothing is
* done.
*
* The methods which will be added from the specified class are not allowed to
* use super or access instance variables, instead they have to use accessors.
*
* @param class_ The class from which the instance methods should be inherited
*/
+ (void)inheritMethodsFromClass: (Class)class_;
/**
* @brief Try to resolve the specified class method.
*
* This method is called if a class method was not found, so that an
* implementation can be provided at runtime.
*
* @return Whether the method has been added to the class
*/
+ (bool)resolveClassMethod: (SEL)selector;
/**
* @brief Try to resolve the specified instance method.
*
* This method is called if an instance method was not found, so that an
* implementation can be provided at runtime.
*
* @return Whether the method has been added to the class
*/
+ (bool)resolveInstanceMethod: (SEL)selector;
/**
* @brief Returns the class.
*
* This method exists so that classes can be used in collections requiring
* conformance to the OFCopying protocol.
*
* @return The class of the object
*/
+ (id)copy;
/**
* @brief Initializes an already allocated object.
*
* Derived classes may override this, but need to use the following pattern:
* @code
* self = [super init];
*
* @try {
* // Custom initialization code goes here.
* } @catch (id e) {
* [self release];
* @throw e;
* }
*
* return self;
* @endcode
*
* With ARC enabled, the following pattern needs to be used instead:
* @code
* self = [super init];
*
* // Custom initialization code goes here.
*
* return self;
* @endcode
*
* @ref init may never return `nil`, instead an exception (for example
* @ref OFInitializationFailedException) should be thrown.
*
* @return An initialized object
*/
- (instancetype)init;
/**
* @brief Returns the method signature for the specified selector.
*
* @param selector The selector for which the method signature should be
* returned
* @return The method signature for the specified selector
*/
- (nullable OFMethodSignature *)methodSignatureForSelector: (SEL)selector;
/**
* @brief Deallocates the object.
*
* It is automatically called when the retain count reaches zero.
*
* This also frees all memory in its memory pool.
*/
- (void)dealloc;
/**
* @brief Performs the specified selector after the specified delay.
*
* @param selector The selector to perform
* @param delay The delay after which the selector will be performed
*/
- (void)performSelector: (SEL)selector afterDelay: (OFTimeInterval)delay;
/**
* @brief Performs the specified selector with the specified object after the
* specified delay.
*
* @param selector The selector to perform
* @param object The object that is passed to the method specified by the
* selector
* @param delay The delay after which the selector will be performed
*/
- (void)performSelector: (SEL)selector
withObject: (nullable id)object
afterDelay: (OFTimeInterval)delay;
/**
* @brief Performs the specified selector with the specified objects after the
* specified delay.
*
* @param selector The selector to perform
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param delay The delay after which the selector will be performed
*/
- (void)performSelector: (SEL)selector
withObject: (nullable id)object1
withObject: (nullable id)object2
afterDelay: (OFTimeInterval)delay;
/**
* @brief Performs the specified selector with the specified objects after the
* specified delay.
*
* @param selector The selector to perform
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param object3 The third object that is passed to the method specified by the
* selector
* @param delay The delay after which the selector will be performed
*/
- (void)performSelector: (SEL)selector
withObject: (nullable id)object1
withObject: (nullable id)object2
withObject: (nullable id)object3
afterDelay: (OFTimeInterval)delay;
/**
* @brief Performs the specified selector with the specified objects after the
* specified delay.
*
* @param selector The selector to perform
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param object3 The third object that is passed to the method specified by the
* selector
* @param object4 The fourth object that is passed to the method specified by
* the selector
* @param delay The delay after which the selector will be performed
*/
- (void)performSelector: (SEL)selector
withObject: (nullable id)object1
withObject: (nullable id)object2
withObject: (nullable id)object3
withObject: (nullable id)object4
afterDelay: (OFTimeInterval)delay;
#ifdef OF_HAVE_THREADS
/**
* @brief Performs the specified selector on the specified thread.
*
* @param selector The selector to perform
* @param thread The thread on which to perform the selector
* @param waitUntilDone Whether to wait until the perform finished
*/
- (void)performSelector: (SEL)selector
onThread: (OFThread *)thread
waitUntilDone: (bool)waitUntilDone;
/**
* @brief Performs the specified selector on the specified thread with the
* specified object.
*
* @param selector The selector to perform
* @param thread The thread on which to perform the selector
* @param object The object that is passed to the method specified by the
* selector
* @param waitUntilDone Whether to wait until the perform finished
*/
- (void)performSelector: (SEL)selector
onThread: (OFThread *)thread
withObject: (nullable id)object
waitUntilDone: (bool)waitUntilDone;
/**
* @brief Performs the specified selector on the specified thread with the
* specified objects.
*
* @param selector The selector to perform
* @param thread The thread on which to perform the selector
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param waitUntilDone Whether to wait until the perform finished
*/
- (void)performSelector: (SEL)selector
onThread: (OFThread *)thread
withObject: (nullable id)object1
withObject: (nullable id)object2
waitUntilDone: (bool)waitUntilDone;
/**
* @brief Performs the specified selector on the specified thread with the
* specified objects.
*
* @param selector The selector to perform
* @param thread The thread on which to perform the selector
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param object3 The third object that is passed to the method specified by the
* selector
* @param waitUntilDone Whether to wait until the perform finished
*/
- (void)performSelector: (SEL)selector
onThread: (OFThread *)thread
withObject: (nullable id)object1
withObject: (nullable id)object2
withObject: (nullable id)object3
waitUntilDone: (bool)waitUntilDone;
/**
* @brief Performs the specified selector on the specified thread with the
* specified objects.
*
* @param selector The selector to perform
* @param thread The thread on which to perform the selector
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param object3 The third object that is passed to the method specified by the
* selector
* @param object4 The fourth object that is passed to the method specified by
* the selector
* @param waitUntilDone Whether to wait until the perform finished
*/
- (void)performSelector: (SEL)selector
onThread: (OFThread *)thread
withObject: (nullable id)object1
withObject: (nullable id)object2
withObject: (nullable id)object3
withObject: (nullable id)object4
waitUntilDone: (bool)waitUntilDone;
/**
* @brief Performs the specified selector on the main thread.
*
* @param selector The selector to perform
* @param waitUntilDone Whether to wait until the perform finished
*/
- (void)performSelectorOnMainThread: (SEL)selector
waitUntilDone: (bool)waitUntilDone;
/**
* @brief Performs the specified selector on the main thread with the specified
* object.
*
* @param selector The selector to perform
* @param object The object that is passed to the method specified by the
* selector
* @param waitUntilDone Whether to wait until the perform finished
*/
- (void)performSelectorOnMainThread: (SEL)selector
withObject: (nullable id)object
waitUntilDone: (bool)waitUntilDone;
/**
* @brief Performs the specified selector on the main thread with the specified
* objects.
*
* @param selector The selector to perform
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param waitUntilDone Whether to wait until the perform finished
*/
- (void)performSelectorOnMainThread: (SEL)selector
withObject: (nullable id)object1
withObject: (nullable id)object2
waitUntilDone: (bool)waitUntilDone;
/**
* @brief Performs the specified selector on the main thread with the specified
* objects.
*
* @param selector The selector to perform
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param object3 The third object that is passed to the method specified by the
* selector
* @param waitUntilDone Whether to wait until the perform finished
*/
- (void)performSelectorOnMainThread: (SEL)selector
withObject: (nullable id)object1
withObject: (nullable id)object2
withObject: (nullable id)object3
waitUntilDone: (bool)waitUntilDone;
/**
* @brief Performs the specified selector on the main thread with the specified
* objects.
*
* @param selector The selector to perform
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param object3 The third object that is passed to the method specified by the
* selector
* @param object4 The fourth object that is passed to the method specified by
* the selector
* @param waitUntilDone Whether to wait until the perform finished
*/
- (void)performSelectorOnMainThread: (SEL)selector
withObject: (nullable id)object1
withObject: (nullable id)object2
withObject: (nullable id)object3
withObject: (nullable id)object4
waitUntilDone: (bool)waitUntilDone;
/**
* @brief Performs the specified selector on the specified thread after the
* specified delay.
*
* @param selector The selector to perform
* @param thread The thread on which to perform the selector
* @param delay The delay after which the selector will be performed
*/
- (void)performSelector: (SEL)selector
onThread: (OFThread *)thread
afterDelay: (OFTimeInterval)delay;
/**
* @brief Performs the specified selector on the specified thread with the
* specified object after the specified delay.
*
* @param selector The selector to perform
* @param thread The thread on which to perform the selector
* @param object The object that is passed to the method specified by the
* selector
* @param delay The delay after which the selector will be performed
*/
- (void)performSelector: (SEL)selector
onThread: (OFThread *)thread
withObject: (nullable id)object
afterDelay: (OFTimeInterval)delay;
/**
* @brief Performs the specified selector on the specified thread with the
* specified objects after the specified delay.
*
* @param selector The selector to perform
* @param thread The thread on which to perform the selector
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param delay The delay after which the selector will be performed
*/
- (void)performSelector: (SEL)selector
onThread: (OFThread *)thread
withObject: (nullable id)object1
withObject: (nullable id)object2
afterDelay: (OFTimeInterval)delay;
/**
* @brief Performs the specified selector on the specified thread with the
* specified objects after the specified delay.
*
* @param selector The selector to perform
* @param thread The thread on which to perform the selector
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param object3 The third object that is passed to the method specified by the
* selector
* @param delay The delay after which the selector will be performed
*/
- (void)performSelector: (SEL)selector
onThread: (OFThread *)thread
withObject: (nullable id)object1
withObject: (nullable id)object2
withObject: (nullable id)object3
afterDelay: (OFTimeInterval)delay;
/**
* @brief Performs the specified selector on the specified thread with the
* specified objects after the specified delay.
*
* @param selector The selector to perform
* @param thread The thread on which to perform the selector
* @param object1 The first object that is passed to the method specified by the
* selector
* @param object2 The second object that is passed to the method specified by
* the selector
* @param object3 The third object that is passed to the method specified by the
* selector
* @param object4 The fourth object that is passed to the method specified by
* the selector
* @param delay The delay after which the selector will be performed
*/
- (void)performSelector: (SEL)selector
onThread: (OFThread *)thread
withObject: (nullable id)object1
withObject: (nullable id)object2
withObject: (nullable id)object3
withObject: (nullable id)object4
afterDelay: (OFTimeInterval)delay;
#endif
/**
* @brief This method is called when @ref resolveClassMethod: or
* @ref resolveInstanceMethod: returned false. It should return a target
* to which the message should be forwarded.
*
* @note When the message should not be forwarded, you should not return `nil`,
* but instead return the result of `[super
* forwardingTargetForSelector: selector]`.
*
* @return The target to forward the message to
*/
- (nullable id)forwardingTargetForSelector: (SEL)selector;
/**
* @brief Handles messages which are not understood by the receiver.
*
* @warning If you override this method, you must make sure that it never
* returns!
*
* @param selector The selector not understood by the receiver
* @throw OFNotImplementedException The method is not implemented
*/
- (void)doesNotRecognizeSelector: (SEL)selector OF_NO_RETURN;
@end
/**
* @protocol OFCopying OFObject.h ObjFW/ObjFW.h
*
* @brief A protocol for the creation of copies.
*/
@protocol OFCopying
/**
* @brief Copies the object.
*
* For classes which can be immutable or mutable, this returns an immutable
* copy. If only a mutable version of the class exists, it creates a mutable
* copy.
*
* @return A copy of the object
*/
- (id)copy;
@end
/**
* @protocol OFMutableCopying OFObject.h ObjFW/ObjFW.h
*
* @brief A protocol for the creation of mutable copies.
*
* This protocol is implemented by objects that can be mutable and immutable
* and allows returning a mutable copy.
*/
@protocol OFMutableCopying
/**
* @brief Creates a mutable copy of the object.
*
* @return A mutable copy of the object
*/
- (id)mutableCopy;
@end
/**
* @protocol OFComparing OFObject.h ObjFW/ObjFW.h
*
* @brief A protocol for comparing objects.
*
* This protocol is implemented by objects that can be compared. Its only
* method, @ref compare:, should be overridden with a stronger type.
*/
@protocol OFComparing
/**
* @brief Compares the object to another object.
*
* @param object An object to compare the object to
* @return The result of the comparison
*/
- (OFComparisonResult)compare: (id <OFComparing>)object;
@end
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Allocates memory for the specified number of items of the specified
* size.
*
* To free the allocated memory, use @ref OFFreeMemory.
*
* @param count The number of items to allocate
* @param size The size of each item to allocate
* @return A pointer to the allocated memory. May return NULL if the specified
* size or count is 0.
* @throw OFOutOfMemoryException The allocation failed due to not enough memory
* @throw OFOutOfRangeException The requested `count * size` exceeds the
* address space
*/
extern void *_Nullable OFAllocMemory(size_t count, size_t size)
OF_WARN_UNUSED_RESULT;
/**
* @brief Allocates memory for the specified number of items of the specified
* size and initializes it with zeros.
*
* To free the allocated memory, use @ref OFFreeMemory.
*
* @param size The size of each item to allocate
* @param count The number of items to allocate
* @return A pointer to the allocated memory. May return NULL if the specified
* size or count is 0.
* @throw OFOutOfMemoryException The allocation failed due to not enough memory
* @throw OFOutOfRangeException The requested `count * size` exceeds the
* address space
*/
extern void *_Nullable OFAllocZeroedMemory(size_t count, size_t size)
OF_WARN_UNUSED_RESULT;
/**
* @brief Resizes memory to the specified number of items of the specified size.
*
* To free the allocated memory, use @ref OFFreeMemory.
*
* If the pointer is NULL, this is equivalent to allocating memory.
* If the size or number of items is 0, this is equivalent to freeing memory.
*
* @param pointer A pointer to the already allocated memory
* @param size The size of each item to resize to
* @param count The number of items to resize to
* @return A pointer to the resized memory chunk
* @throw OFOutOfMemoryException The reallocation failed due to not enough
* memory
* @throw OFOutOfRangeException The requested `count * size` exceeds the
* address space
*/
extern void *_Nullable OFResizeMemory(void *_Nullable pointer, size_t count,
size_t size) OF_WARN_UNUSED_RESULT;
/**
* @brief Frees memory allocated by @ref OFAllocMemory, @ref OFAllocZeroedMemory
* or @ref OFResizeMemory.
*
* @param pointer A pointer to the memory to free or nil (passing nil does
* nothing)
*/
extern void OFFreeMemory(void *_Nullable pointer);
#ifdef OF_APPLE_RUNTIME
extern void *_Null_unspecified objc_autoreleasePoolPush(void);
extern void objc_autoreleasePoolPop(void *_Null_unspecified pool);
# ifdef OF_DECLARE_CONSTRUCT_INSTANCE
extern id _Nullable objc_constructInstance(Class _Nullable class_,
void *_Nullable bytes);
extern void *_Nullable objc_destructInstance(id _Nullable object);
# endif
# ifdef OF_DECLARE_SET_ASSOCIATED_OBJECT
typedef enum objc_associationPolicy {
OBJC_ASSOCIATION_ASSIGN = 0,
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
OBJC_ASSOCIATION_RETAIN = OBJC_ASSOCIATION_RETAIN_NONATOMIC | 0x300,
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
OBJC_ASSOCIATION_COPY = OBJC_ASSOCIATION_COPY_NONATOMIC | 0x300
} objc_associationPolicy;
extern void objc_setAssociatedObject(id _Nonnull object,
const void *_Nonnull key, id _Nullable value,
objc_associationPolicy policy);
extern id _Nullable objc_getAssociatedObject(id _Nonnull object,
const void *_Nonnull key);
extern void objc_removeAssociatedObjects(id _Nonnull object);
# endif
#endif
/**
* @brief Allocates a new object.
*
* This is useful to override @ref OFObject#alloc in a subclass that can then
* allocate extra memory in the same memory allocation.
*
* @param class_ The class of which to allocate an object
* @param extraSize Extra space after the ivars to allocate
* @param extraAlignment Alignment of the extra space after the ivars
* @param extra A pointer to set to a pointer to the extra space
* @return The allocated object
*/
extern id OFAllocObject(Class class_, size_t extraSize, size_t extraAlignment,
void *_Nullable *_Nullable extra);
/**
* @brief This function is called when a method is not found.
*
* It can also be called intentionally to indicate that a method is not
* implemetned, for example in an abstract method. However, instead of calling
* OFMethodNotFound directly, it is preferred to do the following:
*
* - (void)abstractMethod
* {
* OF_UNRECOGNIZED_SELECTOR
* }
*
* However, do not use this for init methods. Instead, use the following:
*
* - (instancetype)init
* {
* OF_INVALID_INIT_METHOD
* }
*
* @param self The object which does not have the method
* @param _cmd The selector of the method that does not exist
*/
extern void OF_NO_RETURN_FUNC OFMethodNotFound(id self, SEL _cmd);
/**
* @brief Initializes the specified hash.
*
* @param hash A pointer to the hash to initialize
*/
extern void OFHashInit(unsigned long *_Nonnull hash);
/**
* @brief Returns 16 bit or non-cryptographical randomness.
*
* @return 16 bit or non-cryptographical randomness
*/
extern uint16_t OFRandom16(void);
/**
* @brief Returns 32 bit or non-cryptographical randomness.
*
* @return 32 bit or non-cryptographical randomness
*/
extern uint32_t OFRandom32(void);
/**
* @brief Returns 64 bit or non-cryptographical randomness.
*
* @return 64 bit or non-cryptographical randomness
*/
extern uint64_t OFRandom64(void);
#ifdef __cplusplus
}
#endif
OF_ASSUME_NONNULL_END
#import "OFBlock.h"
#import "OFObject+KeyValueCoding.h"