Modify the interfaces of all collection classes to be compatible with the

new lightweight generics implemenation. (Newer MacOS X/iOS code assuming 
the presence of the generics annotations can otherwise not be compiled with
GNUstep). This should be well-behaved under clang and gcc both. 

Fix NSCache which was copying the cache keys when it really shouldn't
have. Added a few test cases for eviction behaviour.

Few smaller tweaks to avoid compiler warnings.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@39406 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Niels Grewe 2016-02-22 21:04:18 +00:00
parent 4851131f49
commit 28c824a78a
14 changed files with 541 additions and 273 deletions

View file

@ -1,3 +1,28 @@
2016-02-22 Niels Grewe <niels.grewe@halbordnung.de>
* Headers/Foundation/NSObjCRuntime.h: Add macros for backwards-
compatible generics annotations. Also define instancetype if necessary.
* Headers/Foundation/NSArray.h
* Headers/Foundation/NSCache.h
* Headers/Foundation/NSDictionary.h
* Headers/Foundation/NSEnumerator.h
* Headers/Foundation/NSSet.h: Update interfaces for instancetype and
generics.
* Source/NSCache.m: Use NSMapTable instead of NSMutableDictionary.
The API contract for NSCache stipulates that keys are not copied, so
using a dictionary wasn't apropriate.
* Source/NSConnection.m
* Source/NSData.m: Small type safety improvements (mostly to keep the
compiler happy).
* Source/NSDictionary.m: Change id to id<NSCopying> in a few places to
avoid compiler warnings.
* Tests/base/NSCache
* Tests/base/NSCache/TestInfo
* Tests/base/NSCache/basic.m
* Tests/base/NSCache/cache.m:
Test cases eviction from NSCache. Turns out we currently only evict
NSDiscardableContent, while the API documentation seems to suggest that cost
and count based eviction without NSDiscardableContent is also possible.
2016-02-18 Richard Frith-Macdonald <rfm@gnu.org>
* Source/Additions/GSMime.m:

View file

@ -57,43 +57,49 @@ enum
typedef NSUInteger NSBinarySearchingOptions;
#endif
@interface NSArray : NSObject
@interface GS_GENERIC_CLASS(NSArray, __covariant ElementT) : NSObject
<NSCoding, NSCopying, NSMutableCopying, NSFastEnumeration>
+ (id) array;
+ (id) arrayWithArray: (NSArray*)array;
+ (id) arrayWithContentsOfFile: (NSString*)file;
+ (instancetype) array;
+ (instancetype) arrayWithArray: (GS_GENERIC_CLASS(NSArray, ElementT) *)array;
+ (instancetype) arrayWithContentsOfFile: (NSString*)file;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+ (id) arrayWithContentsOfURL: (NSURL*)aURL;
+ (instancetype) arrayWithContentsOfURL: (NSURL*)aURL;
#endif
+ (id) arrayWithObject: (id)anObject;
+ (id) arrayWithObjects: (id)firstObject, ...;
+ (id) arrayWithObjects: (const id[])objects count: (NSUInteger)count;
+ (instancetype) arrayWithObject: (id)anObject;
+ (instancetype) arrayWithObjects: (id)firstObject, ...;
+ (instancetype) arrayWithObjects: (const id[])objects count: (NSUInteger)count;
- (NSArray*) arrayByAddingObject: (id)anObject;
- (NSArray*) arrayByAddingObjectsFromArray: (NSArray*)anotherArray;
- (BOOL) containsObject: anObject;
- (GS_GENERIC_CLASS(NSArray, ElementT) *) arrayByAddingObject:
(GS_GENERIC_TYPE(ElementT))anObject;
- (GS_GENERIC_CLASS(NSArray, ElementT) *) arrayByAddingObjectsFromArray:
(GS_GENERIC_CLASS(NSArray, ElementT)*)anotherArray;
- (BOOL) containsObject: (GS_GENERIC_TYPE(ElementT))anObject;
/** <override-subclass />
* Returns the number of elements contained in the receiver.
*/
- (NSUInteger) count;
- (void) getObjects: (__unsafe_unretained id[])aBuffer;
- (void) getObjects: (__unsafe_unretained id[])aBuffer range: (NSRange)aRange;
- (NSUInteger) indexOfObject: (id)anObject;
- (NSUInteger) indexOfObject: (id)anObject inRange: (NSRange)aRange;
- (NSUInteger) indexOfObjectIdenticalTo: (id)anObject;
- (NSUInteger) indexOfObjectIdenticalTo: (id)anObject inRange: (NSRange)aRange;
- (id) init;
- (id) initWithArray: (NSArray*)array;
- (void) getObjects: (__unsafe_unretained GS_GENERIC_TYPE(ElementT)[])aBuffer;
- (void) getObjects: (__unsafe_unretained GS_GENERIC_TYPE(ElementT)[])aBuffer
range: (NSRange)aRange;
- (NSUInteger) indexOfObject: (GS_GENERIC_TYPE(ElementT))anObject;
- (NSUInteger) indexOfObject: (GS_GENERIC_TYPE(ElementT))anObject
inRange: (NSRange)aRange;
- (NSUInteger) indexOfObjectIdenticalTo: (GS_GENERIC_TYPE(ElementT))anObject;
- (NSUInteger) indexOfObjectIdenticalTo: (GS_GENERIC_TYPE(ElementT))anObject
inRange: (NSRange)aRange;
- (instancetype) init;
- (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (id) initWithArray: (NSArray*)array copyItems: (BOOL)shouldCopy;
- (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array
copyItems: (BOOL)shouldCopy;
#endif
- (id) initWithContentsOfFile: (NSString*)file;
- (instancetype) initWithContentsOfFile: (NSString*)file;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (id) initWithContentsOfURL: (NSURL*)aURL;
- (instancetype) initWithContentsOfURL: (NSURL*)aURL;
#endif
- (id) initWithObjects: firstObject, ...;
- (instancetype) initWithObjects: (GS_GENERIC_TYPE(ElementT)) firstObject, ...;
/** <init /> <override-subclass />
* This should initialize the array with count (may be zero) objects.<br />
@ -102,24 +108,25 @@ typedef NSUInteger NSBinarySearchingOptions;
* and needs to be re-implemented in subclasses in order to have all
* other initialisers work.
*/
- (id) initWithObjects: (const id[])objects
- (instancetype) initWithObjects: (const GS_GENERIC_TYPE(ElementT)[])objects
count: (NSUInteger)count;
- (id) lastObject;
- (GS_GENERIC_TYPE(ElementT)) lastObject;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
- (id) firstObject;
- (GS_GENERIC_TYPE(ElementT)) firstObject;
#endif
/** <override-subclass />
* Returns the object at the specified index.
* Raises an exception of the index is beyond the array.
*/
- (id) objectAtIndex: (NSUInteger)index;
- (GS_GENERIC_TYPE(ElementT)) objectAtIndex: (NSUInteger)index;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
- (NSArray *) objectsAtIndexes: (NSIndexSet *)indexes;
- (GS_GENERIC_CLASS(NSArray, ElementT) *) objectsAtIndexes: (NSIndexSet *)indexes;
#endif
- (id) firstObjectCommonWithArray: (NSArray*)otherArray;
- (GS_GENERIC_TYPE(ElementT)) firstObjectCommonWithArray:
(GS_GENERIC_CLASS(NSArray, ElementT) *)otherArray;
- (BOOL) isEqualToArray: (NSArray*)otherArray;
#if OS_API_VERSION(GS_API_OPENSTEP, GS_API_MACOSX)
@ -132,19 +139,22 @@ typedef NSUInteger NSBinarySearchingOptions;
#endif
- (NSData*) sortedArrayHint;
- (NSArray*) sortedArrayUsingFunction: (NSComparisonResult (*)(id, id, void*))comparator
- (GS_GENERIC_CLASS(NSArray, ElementT)*) sortedArrayUsingFunction:
(NSComparisonResult (*)(id, id, void*))comparator
context: (void*)context;
- (NSArray*) sortedArrayUsingFunction: (NSComparisonResult (*)(id, id, void*))comparator
- (GS_GENERIC_CLASS(NSArray, ElementT)*) sortedArrayUsingFunction:
(NSComparisonResult (*)(id, id, void*))comparator
context: (void*)context
hint: (NSData*)hint;
- (NSArray*) sortedArrayUsingSelector: (SEL)comparator;
- (NSArray*) subarrayWithRange: (NSRange)aRange;
- (GS_GENERIC_CLASS(NSArray, ElementT)*) sortedArrayUsingSelector: (SEL)comparator;
- (GS_GENERIC_CLASS(NSArray, ElementT)*) subarrayWithRange: (NSRange)aRange;
- (NSString*) componentsJoinedByString: (NSString*)separator;
- (NSArray*) pathsMatchingExtensions: (NSArray*)extensions;
- (GS_GENERIC_CLASS(NSArray, NSString*)*) pathsMatchingExtensions:
(GS_GENERIC_CLASS(NSArray, NSString*)*)extensions;
- (NSEnumerator*) objectEnumerator;
- (NSEnumerator*) reverseObjectEnumerator;
- (GS_GENERIC_CLASS(NSEnumerator, ElementT)*) objectEnumerator;
- (GS_GENERIC_CLASS(NSEnumerator, ElementT)*) reverseObjectEnumerator;
- (NSString*) description;
- (NSString*) descriptionWithLocale: (id)locale;
@ -154,14 +164,14 @@ typedef NSUInteger NSBinarySearchingOptions;
- (BOOL) writeToFile: (NSString*)path atomically: (BOOL)useAuxiliaryFile;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (BOOL) writeToURL: (NSURL*)url atomically: (BOOL)useAuxiliaryFile;
- (id) valueForKey: (NSString*)key;
- (void) setValue: (id)value forKey: (NSString*)key;
- (GS_GENERIC_TYPE(ElementT)) valueForKey: (NSString*)key;
- (void) setValue: (GS_GENERIC_TYPE(ElementT))value forKey: (NSString*)key;
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
DEFINE_BLOCK_TYPE(GSEnumeratorBlock, void, id, NSUInteger, BOOL*);
DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, id, NSUInteger, BOOL*);
DEFINE_BLOCK_TYPE(GSEnumeratorBlock, void, GS_GENERIC_TYPE(ElementT), NSUInteger, BOOL*);
DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, GS_GENERIC_TYPE(ElementT), NSUInteger, BOOL*);
/**
* Enumerate over the collection using the given block. The first argument is
* the object and the second is the index in the array. The final argument is
@ -257,7 +267,8 @@ DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, id, NSUInteger, BOOL*);
/** Returns a sorted array using the comparator to determine the
* order of objects.
*/
- (NSArray *) sortedArrayUsingComparator: (NSComparator)comparator;
- (GS_GENERIC_CLASS(NSArray, ElementT) *) sortedArrayUsingComparator:
(NSComparator)comparator;
/** Returns a sorted array using the block to determine the order of objects.
*
@ -265,7 +276,8 @@ DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, id, NSUInteger, BOOL*);
* specifies that it is thread-safe. The NSSortStable bit specifies that
* it should keep equal objects in the same order.
*/
- (NSArray *) sortedArrayWithOptions: (NSSortOptions)options
- (GS_GENERIC_CLASS(NSArray, ElementT) *)
sortedArrayWithOptions: (NSSortOptions)options
usingComparator: (NSComparator)comparator;
/**
@ -283,20 +295,20 @@ DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, id, NSUInteger, BOOL*);
* Accessor for subscripting. This is called by the compiler when you write
* code like anArray[12]. It should not be called directly.
*/
- (id) objectAtIndexedSubscript: (size_t)anIndex;
- (GS_GENERIC_TYPE(ElementT)) objectAtIndexedSubscript: (size_t)anIndex;
@end
@interface NSMutableArray : NSArray
@interface GS_GENERIC_CLASS(NSMutableArray, ElementT) : NSArray
+ (id) arrayWithCapacity: (NSUInteger)numItems;
+ (instancetype) arrayWithCapacity: (NSUInteger)numItems;
/** <override-subclass />
* Adds anObject at the end of the array, thus increasing the size of
* the array. The object is retained upon addition.
*/
- (void) addObject: (id)anObject;
- (void) addObjectsFromArray: (NSArray*)otherArray;
- (void) addObject: (GS_GENERIC_TYPE(ElementT))anObject;
- (void) addObjectsFromArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)otherArray;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (void) exchangeObjectAtIndex: (NSUInteger)i1
withObjectAtIndex: (NSUInteger)i2;
@ -309,7 +321,7 @@ DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, id, NSUInteger, BOOL*);
* and needs to be re-implemented in subclasses in order to have all
* other initialisers work.
*/
- (id) initWithCapacity: (NSUInteger)numItems;
- (instancetype) initWithCapacity: (NSUInteger)numItems;
/** <override-subclass />
* Inserts an object into the receiver at the specified location.<br />
@ -317,9 +329,11 @@ DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, id, NSUInteger, BOOL*);
* The size of the array increases by one.<br />
* The object is retained by the array.
*/
- (void) insertObject: (id)anObject atIndex: (NSUInteger)index;
- (void) insertObject: (GS_GENERIC_TYPE(ElementT))anObject
atIndex: (NSUInteger)index;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
- (void) insertObjects: (NSArray *)objects atIndexes: (NSIndexSet *)indexes;
- (void) insertObjects: (GS_GENERIC_CLASS(NSArray, ElementT) *)objects
atIndexes: (NSIndexSet *)indexes;
#endif
/** <override-subclass />
@ -337,34 +351,38 @@ DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, id, NSUInteger, BOOL*);
* The object is retained by the array.
*/
- (void) replaceObjectAtIndex: (NSUInteger)index
withObject: (id)anObject;
withObject: (GS_GENERIC_TYPE(ElementT))anObject;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
- (void) replaceObjectsAtIndexes: (NSIndexSet *)indexes
withObjects: (NSArray *)objects;
withObjects: (GS_GENERIC_CLASS(NSArray, ElementT)*)objects;
#endif
- (void) replaceObjectsInRange: (NSRange)aRange
withObjectsFromArray: (NSArray*)anArray;
withObjectsFromArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)anArray;
- (void) replaceObjectsInRange: (NSRange)aRange
withObjectsFromArray: (NSArray*)anArray
withObjectsFromArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)anArray
range: (NSRange)anotherRange;
- (void) setArray: (NSArray *)otherArray;
- (void) setArray: (GS_GENERIC_CLASS(NSArray, ElementT) *)otherArray;
- (void) removeAllObjects;
- (void) removeLastObject;
- (void) removeObject: (id)anObject;
- (void) removeObject: (id)anObject inRange: (NSRange)aRange;
- (void) removeObjectIdenticalTo: (id)anObject;
- (void) removeObjectIdenticalTo: (id)anObject inRange: (NSRange)aRange;
- (void) removeObjectsInArray: (NSArray*)otherArray;
- (void) removeObject: (GS_GENERIC_TYPE(ElementT))anObject;
- (void) removeObject: (GS_GENERIC_TYPE(ElementT))anObject
inRange: (NSRange)aRange;
- (void) removeObjectIdenticalTo: (GS_GENERIC_TYPE(ElementT))anObject;
- (void) removeObjectIdenticalTo: (GS_GENERIC_TYPE(ElementT))anObject
inRange: (NSRange)aRange;
- (void) removeObjectsInArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)otherArray;
- (void) removeObjectsInRange: (NSRange)aRange;
- (void) removeObjectsFromIndices: (NSUInteger*)indices
numIndices: (NSUInteger)count;
- (void) sortUsingFunction: (NSComparisonResult (*)(id,id,void*))compare
- (void) sortUsingFunction:
(NSComparisonResult (*)(GS_GENERIC_TYPE(ElementT),
GS_GENERIC_TYPE(ElementT),void*))compare
context: (void*)context;
- (void) sortUsingSelector: (SEL)comparator;
@ -384,7 +402,8 @@ DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, id, NSUInteger, BOOL*);
/**
* Set method called by the compiler with array subscripting.
*/
- (void) setObject: (id)anObject atIndexedSubscript: (size_t)anIndex;
- (void) setObject: (GS_GENERIC_TYPE(ElementT))anObject
atIndexedSubscript: (size_t)anIndex;
@end
#if defined(__cplusplus)

View file

@ -35,10 +35,10 @@ extern "C" {
#endif
@class NSString;
@class NSMutableDictionary;
@class NSMutableArray;
@class NSMapTable;
@class GS_GENERIC_CLASS(NSMutableArray, ElementT);
@interface NSCache : NSObject
@interface GS_GENERIC_CLASS(NSCache, KeyT, ValT) : NSObject
{
#if GS_EXPOSE(NSCache)
@private
@ -55,9 +55,9 @@ extern "C" {
/** Name of this cache. */
NSString *_name;
/** The mapping from names to objects in this cache. */
NSMutableDictionary *_objects;
NSMapTable *_objects;
/** LRU ordering of all potentially-evictable objects in this cache. */
NSMutableArray *_accesses;
GS_GENERIC_CLASS(NSMutableArray, ValT) *_accesses;
/** Total number of accesses to objects */
int64_t _totalAccesses;
#endif
@ -76,6 +76,11 @@ extern "C" {
*/
- (NSUInteger) countLimit;
/**
* Returns the total cost of all objects held in the cache.
*/
- (NSUInteger) totalCostLimit;
/**
* Returns the cache's delegate.
*/
@ -96,7 +101,8 @@ extern "C" {
/**
* Returns an object associated with the specified key in this cache.
*/
- (id) objectForKey: (id)key;
- (GS_GENERIC_TYPE(ValT)) objectForKey:
(GS_GENERIC_TYPE(KeyT))key;
/**
* Removes all objects from this cache.
@ -106,7 +112,7 @@ extern "C" {
/**
* Removes the object associated with the given key.
*/
- (void) removeObjectForKey: (id)key;
- (void) removeObjectForKey: (GS_GENERIC_TYPE(KeyT))key;
/**
* Sets the maximum number of objects permitted in this cache. This limit is
@ -137,12 +143,15 @@ extern "C" {
* total cost below the value set with -setTotalCostLimit: by discarding the
* contents of objects which implement the NSDiscardableContent protocol.
*/
- (void) setObject: (id)obj forKey: (id)key cost: (NSUInteger)num;
- (void) setObject: (GS_GENERIC_TYPE(ValT))obj
forKey: (GS_GENERIC_TYPE(KeyT))key
cost: (NSUInteger)num;
/**
* Adds an object to the cache without associating a cost with it.
*/
- (void) setObject: (id)obj forKey: (id)key;
- (void) setObject: (GS_GENERIC_TYPE(ValT))obj
forKey: (GS_GENERIC_TYPE(KeyT))key;
/**
* Sets the maximum total cost for objects stored in this cache. This limit is

View file

@ -33,25 +33,34 @@
extern "C" {
#endif
@class NSArray, NSSet, NSString, NSURL;
@class GS_GENERIC_CLASS(NSArray, ElementT);
@class GS_GENERIC_CLASS(NSSet, ElementT);
@class NSString, NSURL;
@interface NSDictionary : NSObject <NSCoding, NSCopying, NSMutableCopying, NSFastEnumeration>
+ (id) dictionary;
+ (id) dictionaryWithContentsOfFile: (NSString*)path;
@interface GS_GENERIC_CLASS(NSDictionary,
__covariant KeyT:id<NSCopying>, __covariant ValT)
: NSObject <NSCoding, NSCopying, NSMutableCopying, NSFastEnumeration>
+ (instancetype) dictionary;
+ (instancetype) dictionaryWithContentsOfFile: (NSString*)path;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+ (id) dictionaryWithContentsOfURL: (NSURL*)aURL;
+ (instancetype) dictionaryWithContentsOfURL: (NSURL*)aURL;
#endif
+ (id) dictionaryWithDictionary: (NSDictionary*)otherDictionary;
+ (id) dictionaryWithObject: (id)object forKey: (id)key;
+ (id) dictionaryWithObjects: (NSArray*)objects forKeys: (NSArray*)keys;
+ (id) dictionaryWithObjects: (const id[])objects
forKeys: (const id <NSCopying>[])keys
+ (instancetype) dictionaryWithDictionary: (NSDictionary*)otherDictionary;
+ (instancetype) dictionaryWithObject: (GS_GENERIC_TYPE(ValT))object
forKey:
(GS_GENERIC_TYPE(KeyT))key;
+ (instancetype) dictionaryWithObjects: (GS_GENERIC_CLASS(NSArray,ValT)*)objects
forKeys: (GS_GENERIC_CLASS(NSArray,KeyT)*)keys;
+ (instancetype) dictionaryWithObjects: (const GS_GENERIC_TYPE(ValT)[])objects
forKeys:
(const GS_GENERIC_TYPE_F(KeyT,id<NSCopying>)[])keys
count: (NSUInteger)count;
+ (id) dictionaryWithObjectsAndKeys: (id)firstObject, ...;
+ (instancetype) dictionaryWithObjectsAndKeys: (id)firstObject, ...;
- (NSArray*) allKeys;
- (NSArray*) allKeysForObject: (id)anObject;
- (NSArray*) allValues;
- (GS_GENERIC_CLASS(NSArray,KeyT)*) allKeys;
- (GS_GENERIC_CLASS(NSArray,KeyT)*) allKeysForObject:
(GS_GENERIC_TYPE(ValT))anObject;
- (GS_GENERIC_CLASS(NSArray,ValT)*) allValues;
- (NSUInteger) count; // Primitive
- (NSString*) description;
- (NSString*) descriptionInStringsFileFormat;
@ -60,47 +69,58 @@ extern "C" {
indent: (NSUInteger)level;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
DEFINE_BLOCK_TYPE(GSKeysAndObjectsEnumeratorBlock, void, id, id, BOOL*);
DEFINE_BLOCK_TYPE(GSKeysAndObjectsEnumeratorBlock, void,
GS_GENERIC_TYPE_F(KeyT,id<NSCopying>), GS_GENERIC_TYPE(ValT), BOOL*);
- (void) enumerateKeysAndObjectsUsingBlock:
(GSKeysAndObjectsEnumeratorBlock)aBlock;
- (void) enumerateKeysAndObjectsWithOptions: (NSEnumerationOptions)opts
usingBlock: (GSKeysAndObjectsEnumeratorBlock)aBlock;
#endif
- (void) getObjects: (__unsafe_unretained id[])objects
andKeys: (__unsafe_unretained id[])keys;
- (id) init;
- (id) initWithContentsOfFile: (NSString*)path;
- (void) getObjects: (__unsafe_unretained GS_GENERIC_TYPE(ValT)[])objects
andKeys:
(__unsafe_unretained GS_GENERIC_TYPE_F(KeyT,id<NSCopying>)[])keys;
- (instancetype) init;
- (instancetype) initWithContentsOfFile: (NSString*)path;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (id) initWithContentsOfURL: (NSURL*)aURL;
- (instancetype) initWithContentsOfURL: (NSURL*)aURL;
#endif
- (id) initWithDictionary: (NSDictionary*)otherDictionary;
- (id) initWithDictionary: (NSDictionary*)other copyItems: (BOOL)shouldCopy;
- (id) initWithObjects: (NSArray*)objects forKeys: (NSArray*)keys;
- (id) initWithObjectsAndKeys: (id)firstObject, ...;
- (id) initWithObjects: (const id[])objects
forKeys: (const id <NSCopying>[])keys
- (instancetype) initWithDictionary:
(GS_GENERIC_CLASS(NSDictionary,KeyT, ValT)*)otherDictionary;
- (id) initWithDictionary: (GS_GENERIC_CLASS(NSDictionary,KeyT, ValT)*)other
copyItems: (BOOL)shouldCopy;
- (id) initWithObjects: (GS_GENERIC_CLASS(NSArray,KeyT)*)objects
forKeys: (GS_GENERIC_CLASS(NSArray,ValT)*)keys;
- (id) initWithObjectsAndKeys: (GS_GENERIC_TYPE(ValT))firstObject, ...;
- (id) initWithObjects: (const GS_GENERIC_TYPE(ValT)[])objects
forKeys: (const GS_GENERIC_TYPE_F(KeyT,id<NSCopying>)[])keys
count: (NSUInteger)count; // Primitive
- (BOOL) isEqualToDictionary: (NSDictionary*)other;
- (BOOL) isEqualToDictionary: (GS_GENERIC_CLASS(NSDictionary,KeyT, ValT)*)other;
- (NSEnumerator*) keyEnumerator; // Primitive
- (GS_GENERIC_CLASS(NSEnumerator,KeyT)*) keyEnumerator; // Primitive
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
DEFINE_BLOCK_TYPE(GSKeysAndObjectsPredicateBlock, BOOL, id, id, BOOL*);
- (NSSet*) keysOfEntriesPassingTest: (GSKeysAndObjectsPredicateBlock)aPredicate;
- (NSSet*) keysOfEntriesWithOptions: (NSEnumerationOptions)opts
DEFINE_BLOCK_TYPE(GSKeysAndObjectsPredicateBlock, BOOL,
GS_GENERIC_TYPE_F(KeyT,id<NSCopying>), GS_GENERIC_TYPE(ValT), BOOL*);
- (GS_GENERIC_CLASS(NSSet,KeyT)*) keysOfEntriesPassingTest:
(GSKeysAndObjectsPredicateBlock)aPredicate;
- (GS_GENERIC_CLASS(NSSet,KeyT)*) keysOfEntriesWithOptions:
(NSEnumerationOptions)opts
passingTest: (GSKeysAndObjectsPredicateBlock)aPredicate;
#endif
- (NSArray*) keysSortedByValueUsingSelector: (SEL)comp;
- (NSEnumerator*) objectEnumerator; // Primitive
- (id) objectForKey: (id)aKey; // Primitive
- (NSArray*) objectsForKeys: (NSArray*)keys notFoundMarker: (id)marker;
- (GS_GENERIC_CLASS(NSArray,ValT)*) keysSortedByValueUsingSelector: (SEL)comp;
- (GS_GENERIC_CLASS(NSEnumerator,ValT)*) objectEnumerator; // Primitive
- (GS_GENERIC_TYPE(ValT)) objectForKey:
(GS_GENERIC_TYPE(KeyT))aKey; // Primitive
- (GS_GENERIC_CLASS(NSArray,ValT)*) objectsForKeys:
(GS_GENERIC_CLASS(NSArray,KeyT)*)keys
notFoundMarker: (GS_GENERIC_TYPE(ValT))marker;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (id) valueForKey: (NSString*)key;
- (GS_GENERIC_TYPE(ValT)) valueForKey: (NSString*)key;
#endif
- (BOOL) writeToFile: (NSString*)path atomically: (BOOL)useAuxiliaryFile;
@ -111,29 +131,39 @@ DEFINE_BLOCK_TYPE(GSKeysAndObjectsPredicateBlock, BOOL, id, id, BOOL*);
/**
* Method called by array subscripting.
*/
- (id) objectForKeyedSubscript: (id)aKey;
- (GS_GENERIC_TYPE(ValT)) objectForKeyedSubscript:
(GS_GENERIC_TYPE(KeyT))aKey;
@end
@interface NSMutableDictionary: NSDictionary
@interface GS_GENERIC_CLASS(NSMutableDictionary, KeyT:id<NSCopying>, ValT) :
GS_GENERIC_CLASS(NSDictionary, KeyT, ValT)
+ (id) dictionaryWithCapacity: (NSUInteger)numItems;
+ (instancetype) dictionaryWithCapacity: (NSUInteger)numItems;
- (void) addEntriesFromDictionary: (NSDictionary*)otherDictionary;
- (id) initWithCapacity: (NSUInteger)numItems; // Primitive
- (void) addEntriesFromDictionary:
(GS_GENERIC_CLASS(NSDictionary, KeyT, ValT)*)otherDictionary;
- (instancetype) initWithCapacity: (NSUInteger)numItems; // Primitive
- (void) removeAllObjects;
- (void) removeObjectForKey: (id)aKey; // Primitive
- (void) removeObjectsForKeys: (NSArray*)keyArray;
- (void) setObject: (id)anObject forKey: (id)aKey; // Primitive
- (void) setDictionary: (NSDictionary*)otherDictionary;
/**
* Removes the object with the specified key from the receiver. This method
* is primitive.
*/
- (void) removeObjectForKey: (GS_GENERIC_TYPE(KeyT))aKey;
- (void) removeObjectsForKeys: (GS_GENERIC_CLASS(NSArray, KeyT) *)keyArray;
- (void) setObject: (GS_GENERIC_TYPE(ValT))anObject
forKey: (GS_GENERIC_TYPE(KeyT))aKey; // Primitive
- (void) setDictionary:
(GS_GENERIC_CLASS(NSDictionary, KeyT, ValT)*)otherDictionary;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (void) setValue: (id)value forKey: (NSString*)key;
- (void) takeStoredValue: (id)value forKey: (NSString*)key;
- (void) takeValue: (id)value forKey: (NSString*)key;
- (void) setValue: (GS_GENERIC_TYPE(ValT))value forKey: (NSString*)key;
- (void) takeStoredValue: (GS_GENERIC_TYPE(ValT))value forKey: (NSString*)key;
- (void) takeValue: (GS_GENERIC_TYPE(ValT))value forKey: (NSString*)key;
#endif
/**
* Method called by array subscripting.
*/
- (void) setObject: (id)anObject forKeyedSubscript: (id)aKey;
- (void) setObject: (GS_GENERIC_TYPE(ValT))anObject
forKeyedSubscript: (GS_GENERIC_TYPE(KeyT))aKey;
@end

View file

@ -30,10 +30,13 @@
#import <Foundation/NSObject.h>
#if defined(__cplusplus)
extern "C" {
#endif
@class GS_GENERIC_CLASS(NSArray, ElementT);
typedef struct
{
unsigned long state;
@ -48,9 +51,9 @@ typedef struct
count: (NSUInteger)len;
@end
@interface NSEnumerator : NSObject <NSFastEnumeration>
- (NSArray *) allObjects;
- (id) nextObject;
@interface GS_GENERIC_CLASS(NSEnumerator, IterT) : NSObject <NSFastEnumeration>
- (GS_GENERIC_CLASS(NSArray, IterT) *) allObjects;
- (GS_GENERIC_TYPE(IterT)) nextObject;
@end
#if defined(__cplusplus)

View file

@ -162,6 +162,25 @@ extern "C" {
# define NS_ASSUME_NONNULL_END
#endif
/*
* Backwards compatibility macro for instance type.
*/
#if !__has_feature(objc_instancetype)
# define instancetype id
#endif
/*
* Backwards compatibility macros for Objective-C lightweight generics.
*/
#if __has_feature(objc_generics)
# define GS_GENERIC_CLASS(clz, ...) clz<__VA_ARGS__>
# define GS_GENERIC_TYPE_F(typeRef, fallback) typeRef
#else
# define GS_GENERIC_CLASS(clz, ...) clz
# define GS_GENERIC_TYPE_F(typeRef, fallback) fallback
#endif
#define GS_GENERIC_TYPE(typeRef) GS_GENERIC_TYPE_F(typeRef, id)
/** Bitfield used to specify options to control enumeration over collections.
*/
typedef NS_OPTIONS(NSUInteger, NSEnumerationOptions)

View file

@ -38,38 +38,45 @@
extern "C" {
#endif
@class NSArray, NSString, NSEnumerator, NSDictionary;
@class GS_GENERIC_CLASS(NSArray, ElementT);
@class GS_GENERIC_CLASS(NSEnumerator, ElementT);
@class GS_GENERIC_CLASS(NSDictionary, KeyT:id<NSCopying>, ValT);
@class NSString;
@interface NSSet : NSObject <NSCoding, NSCopying, NSMutableCopying, NSFastEnumeration>
@interface GS_GENERIC_CLASS(NSSet, __covariant ElementT) : NSObject <NSCoding,
NSCopying,
NSMutableCopying,
NSFastEnumeration>
+ (id) set;
+ (id) setWithArray: (NSArray*)objects;
+ (id) setWithObject: (id)anObject;
+ (id) setWithObjects: (id)firstObject, ...;
+ (instancetype) set;
+ (instancetype) setWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)objects;
+ (instancetype) setWithObject: (GS_GENERIC_TYPE(ElementT))anObject;
+ (instancetype) setWithObjects: (GS_GENERIC_TYPE(ElementT))firstObject, ...;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+ (id) setWithObjects: (const id[])objects
+ (instancetype) setWithObjects: (const GS_GENERIC_TYPE(ElementT)[])objects
count: (NSUInteger)count;
#endif
+ (id) setWithSet: (NSSet*)aSet;
+ (instancetype) setWithSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)aSet;
- (NSArray*) allObjects;
- (id) anyObject;
- (BOOL) containsObject: (id)anObject;
- (GS_GENERIC_CLASS(NSArray, ElementT)*) allObjects;
- (GS_GENERIC_TYPE(ElementT)) anyObject;
- (BOOL) containsObject: (GS_GENERIC_TYPE(ElementT))anObject;
- (NSUInteger) count;
- (NSString*) description;
- (NSString*) descriptionWithLocale: (id)locale;
- (id) init;
- (id) initWithArray: (NSArray*)other;
- (id) initWithObjects: (id)firstObject, ...;
- (id) initWithObjects: (const id[])objects
- (instancetype) init;
- (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)other;
- (instancetype) initWithObjects: (GS_GENERIC_TYPE(ElementT))firstObject, ...;
- (instancetype) initWithObjects: (const GS_GENERIC_TYPE(ElementT)[])objects
count: (NSUInteger)count;
- (id) initWithSet: (NSSet*)other;
- (id) initWithSet: (NSSet*)other copyItems: (BOOL)flag;
- (instancetype) initWithSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)other;
- (instancetype) initWithSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)other
copyItems: (BOOL)flag;
- (BOOL) intersectsSet: (NSSet*)otherSet;
- (BOOL) isEqualToSet: (NSSet*)other;
- (BOOL) isSubsetOfSet: (NSSet*)otherSet;
- (BOOL) intersectsSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)otherSet;
- (BOOL) isEqualToSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)other;
- (BOOL) isSubsetOfSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)otherSet;
- (void) makeObjectsPerform: (SEL)aSelector;
- (void) makeObjectsPerform: (SEL)aSelector withObject: (id)argument;
@ -77,13 +84,13 @@ extern "C" {
- (void) makeObjectsPerformSelector: (SEL)aSelector;
- (void) makeObjectsPerformSelector: (SEL)aSelector withObject: (id)argument;
#endif
- (id) member: (id)anObject;
- (NSEnumerator*) objectEnumerator;
- (GS_GENERIC_TYPE(ElementT)) member: (GS_GENERIC_TYPE(ElementT))anObject;
- (GS_GENERIC_CLASS(NSEnumerator, ElementT)*) objectEnumerator;
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
DEFINE_BLOCK_TYPE(GSSetEnumeratorBlock, void, id, BOOL*);
DEFINE_BLOCK_TYPE(GSSetFilterBlock, BOOL, id, BOOL*);
DEFINE_BLOCK_TYPE(GSSetEnumeratorBlock, void, GS_GENERIC_TYPE(ElementT), BOOL*);
DEFINE_BLOCK_TYPE(GSSetFilterBlock, BOOL, GS_GENERIC_TYPE(ElementT), BOOL*);
/**
* Enumerate over the collection using a given block. The first argument is
@ -106,40 +113,46 @@ DEFINE_BLOCK_TYPE(GSSetFilterBlock, BOOL, id, BOOL*);
- (void) enumerateObjectsWithOptions: (NSEnumerationOptions)opts
usingBlock: (GSSetEnumeratorBlock)aBlock;
- (NSSet *) objectsPassingTest: (GSSetFilterBlock)aBlock;
- (GS_GENERIC_CLASS(NSSet, ElementT) *) objectsPassingTest:
(GSSetFilterBlock)aBlock;
- (NSSet *) objectsWithOptions: (NSEnumerationOptions)opts
- (GS_GENERIC_CLASS(NSSet, ElementT) *) objectsWithOptions:
(NSEnumerationOptions)opts
passingTest: (GSSetFilterBlock)aBlock;
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST)
- (NSSet *) setByAddingObject: (id)anObject;
- (NSSet *) setByAddingObjectsFromSet: (NSSet *)other;
- (NSSet *) setByAddingObjectsFromArray: (NSArray *)other;
- (GS_GENERIC_CLASS(NSSet, ElementT) *) setByAddingObject:
(GS_GENERIC_TYPE(ElementT))anObject;
- (GS_GENERIC_CLASS(NSSet, ElementT) *) setByAddingObjectsFromSet:
(GS_GENERIC_CLASS(NSSet, ElementT) *)other;
- (GS_GENERIC_CLASS(NSSet, ElementT) *) setByAddingObjectsFromArray:
(GS_GENERIC_CLASS(NSArray, ElementT) *)other;
#endif
@end
@interface NSMutableSet: NSSet
@interface GS_GENERIC_CLASS(NSMutableSet, ElementT):
GS_GENERIC_CLASS(NSSet, ElementT)
+ (id) setWithCapacity: (NSUInteger)numItems;
+ (instancetype) setWithCapacity: (NSUInteger)numItems;
- (void) addObject: (id)anObject;
- (void) addObjectsFromArray: (NSArray*)array;
- (id) initWithCapacity: (NSUInteger)numItems;
- (void) intersectSet: (NSSet*)other;
- (void) minusSet: (NSSet*)other;
- (void) addObject: (GS_GENERIC_TYPE(ElementT))anObject;
- (void) addObjectsFromArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array;
- (instancetype) initWithCapacity: (NSUInteger)numItems;
- (void) intersectSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)other;
- (void) minusSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)other;
- (void) removeAllObjects;
- (void) removeObject: (id)anObject;
- (void) removeObject: (GS_GENERIC_TYPE(ElementT))anObject;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (void) setSet: (NSSet*)other;
- (void) setSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)other;
#endif
- (void) unionSet: (NSSet*)other;
- (void) unionSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)other;
@end
@interface NSCountedSet : NSMutableSet
@interface GS_GENERIC_CLASS(NSCountedSet, ElementT) :
GS_GENERIC_CLASS(NSMutableSet, ElementT)
- (NSUInteger) countForObject: (id)anObject;
- (NSUInteger) countForObject: (GS_GENERIC_TYPE(ElementT))anObject;
@end
@ -148,7 +161,7 @@ DEFINE_BLOCK_TYPE(GSSetFilterBlock, BOOL, id, BOOL*);
/**
* Utility methods for using a counted set to handle uniquing of objects.
*/
@interface NSCountedSet (GNU_Uniquing)
@interface GS_GENERIC_CLASS(NSCountedSet, ElementT) (GNU_Uniquing)
/**
* <p>
* This method removes from the set all objects whose count is
@ -178,7 +191,8 @@ DEFINE_BLOCK_TYPE(GSSetFilterBlock, BOOL, id, BOOL*);
* </code>
* </p>
*/
- (id) unique: (id) NS_CONSUMED anObject NS_RETURNS_RETAINED;
- (GS_GENERIC_TYPE(ElementT)) unique:
(GS_GENERIC_TYPE(ElementT)) NS_CONSUMED anObject NS_RETURNS_RETAINED;
@end
/*

View file

@ -28,7 +28,7 @@
#import "Foundation/NSArray.h"
#import "Foundation/NSCache.h"
#import "Foundation/NSDictionary.h"
#import "Foundation/NSMapTable.h"
#import "Foundation/NSEnumerator.h"
/**
@ -60,7 +60,7 @@
{
return nil;
}
_objects = [NSMutableDictionary new];
ASSIGN(_objects,[NSMapTable strongToStrongObjectsMapTable]);
_accesses = [NSMutableArray new];
return self;
}

View file

@ -1421,31 +1421,34 @@ static NSLock *cached_proxies_gate = nil;
*/
- (NSArray*) localObjects
{
NSMutableArray *c;
NSArray *a;
/* Don't assert (IisValid); */
GS_M_LOCK(IrefGate);
if (IlocalObjects != 0)
{
GSIMapEnumerator_t enumerator;
GSIMapNode node;
enumerator = GSIMapEnumeratorForMap(IlocalObjects);
node = GSIMapEnumeratorNextNode(&enumerator);
c = [NSMutableArray arrayWithCapacity: IlocalObjects->nodeCount];
NSMutableArray *c =
[NSMutableArray arrayWithCapacity: IlocalObjects->nodeCount];
while (node != 0)
{
[c addObject: node->key.obj];
node = GSIMapEnumeratorNextNode(&enumerator);
}
a = c;
}
else
{
c = [NSArray array];
a = [NSArray array];
}
GSM_UNLOCK(IrefGate);
return c;
return a;
}
/**
@ -4044,4 +4047,3 @@ static NSLock *cached_proxies_gate = nil;
}
}
@end

View file

@ -1918,13 +1918,11 @@ failure:
if (useAuxiliaryFile)
{
NSFileManager *mgr = [NSFileManager defaultManager];
NSMutableDictionary *att = nil;
NSDictionary *att = nil;
if ([mgr fileExistsAtPath: path])
{
att = [[mgr fileAttributesAtPath: path
traverseLink: YES] mutableCopy];
IF_NO_GC(AUTORELEASE(att));
att = [mgr fileAttributesAtPath: path traverseLink: YES];
}
c = rename(thePath, theRealPath);
@ -1937,18 +1935,20 @@ failure:
if (att != nil)
{
NSMutableDictionary *mAtt = [att mutableCopy];
IF_NO_GC(AUTORELEASE(mAtt));
/*
* We have created a new file - so we attempt to make it's
* attributes match that of the original.
*/
[att removeObjectForKey: NSFileSize];
[att removeObjectForKey: NSFileModificationDate];
[att removeObjectForKey: NSFileReferenceCount];
[att removeObjectForKey: NSFileSystemNumber];
[att removeObjectForKey: NSFileSystemFileNumber];
[att removeObjectForKey: NSFileDeviceIdentifier];
[att removeObjectForKey: NSFileType];
if ([mgr changeFileAttributes: att atPath: path] == NO)
[mAtt removeObjectForKey: NSFileSize];
[mAtt removeObjectForKey: NSFileModificationDate];
[mAtt removeObjectForKey: NSFileReferenceCount];
[mAtt removeObjectForKey: NSFileSystemNumber];
[mAtt removeObjectForKey: NSFileSystemFileNumber];
[mAtt removeObjectForKey: NSFileDeviceIdentifier];
[mAtt removeObjectForKey: NSFileType];
if ([mgr changeFileAttributes: mAtt atPath: path] == NO)
{
NSWarnMLog(@"Unable to correctly set all attributes for '%@'",
path);
@ -4420,4 +4420,3 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
@end
#endif /* HAVE_SHMCTL */

View file

@ -863,7 +863,7 @@ static SEL appSel;
}
- (void)getObjects: (__unsafe_unretained id[])objects
andKeys: (__unsafe_unretained id[])keys
andKeys: (__unsafe_unretained id<NSCopying>[])keys
{
int i=0;
FOR_IN(id, key, self)
@ -1242,7 +1242,7 @@ compareIt(id o1, id o2, void* context)
if (count > 0)
{
NSEnumerator *enumerator = [self keyEnumerator];
NSObject *k;
NSObject<NSCopying> *k = nil;
while ((k = [enumerator nextObject]) != nil)
{

View file

View file

@ -0,0 +1,17 @@
#import "ObjectTesting.h"
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSCache.h>
int main()
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
NSCache *testObj;
testObj = [[NSCache new] autorelease];
[testObj setObject: @"hello" forKey: @"there"];
test_alloc(@"NSCache");
test_NSObject(@"NSCache", [NSArray arrayWithObject: testObj]);
[arp release]; arp = nil;
return 0;
}

131
Tests/base/NSCache/cache.m Normal file
View file

@ -0,0 +1,131 @@
#import "ObjectTesting.h"
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSCache.h>
@interface TestObject : NSObject <NSDiscardableContent>
{
BOOL _discarded;
}
@end
@implementation TestObject
- (BOOL)beginContentAccess
{
return YES;
}
- (void)endContentAccess
{
}
- (void)discardContentIfPossible
{
_discarded = YES;
}
- (BOOL)isContentDiscarded
{
return _discarded;
}
@end
int main()
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
NSCache *cache = [[NSCache new] autorelease];
[cache setName: @"Foo"];
PASS_EQUAL(@"Foo", [cache name], "Name can be set an accessed");
[cache setCountLimit: 2];
PASS(2 == [cache countLimit], "Count limit can be set and accessed");
[cache setTotalCostLimit: 3];
PASS(3 == [cache totalCostLimit], "Total cost limit can be set and accessed");
[cache setObject: @"bar" forKey: @"foo"];
PASS_EQUAL(@"bar", [cache objectForKey: @"foo"],
"Cached object can be returned");
/*
* NOTE: The following to test sets currently won't work. The only available
* eviction strategy is to evict under the following conditions:
*
* - evictsObjectsWithDiscardedContent is set on the receiver
* - the cached object implements NSDiscardableContent
* - the content is actually discarded
*/
START_SET("count-based eviction")
testHopeful = YES;
/* Let's test count based eviction: We add two more items and expect the
* first one (foo) to be removed because the count limit is two
*/
[cache setObject: @"baz" forKey: @"bar"];
NSUInteger i = 0;
for (i = 0; i < 50; i++)
{
/* We need to heat this object in the cache so that the first one
* becomes elligible for eviction
*/
[cache objectForKey: @"bar"];
}
[cache setObject: @"frubble" forKey: @"baz"];
PASS_EQUAL(@"frubble", [cache objectForKey: @"baz"],
"LRU object retained on count overflow");
PASS_EQUAL(@"baz", [cache objectForKey: @"bar"],
"second object retained on count overflow");
PASS(nil == [cache objectForKey: @"foo"], "Oldest object evicted");
END_SET("count-based eviction")
[cache removeAllObjects];
START_SET("cost-based eviction")
testHopeful = YES;
[cache setObject: @"bar" forKey: @"foo" cost: 2];
// This should push out the previous object because the cumulative cost (4)
// exceeds the limit (3)
[cache setObject: @"baz" forKey: @"bar" cost: 2];
PASS_EQUAL(@"baz", [cache objectForKey: @"bar"],
"LRU object retained on cost overflow");
PASS(nil == [cache objectForKey: @"foo"], "Overflowing object evicted");
END_SET("cost-based eviction")
[cache removeAllObjects];
START_SET("eviction of discardable content")
cache = [[NSCache new] autorelease];
[cache setCountLimit: 1];
[cache setEvictsObjectsWithDiscardedContent: YES];
TestObject *a = [[TestObject new] autorelease];
TestObject *b = [[TestObject new] autorelease];
[cache setObject: a forKey: @"foo"];
[cache setObject: b forKey: @"bar"];
PASS_EQUAL(b, [cache objectForKey: @"bar"],
"LRU object retained on count overflow");
PASS(nil == [cache objectForKey: @"foo"],
"Overflowing object evicted on count overflow");
PASS([a isContentDiscarded],
"Cache did call -discardContentIfPossible on cached object");
[cache removeAllObjects];
[cache setCountLimit: 0];
[cache setTotalCostLimit: 3];
a = [[TestObject new] autorelease];
b = [[TestObject new] autorelease];
[cache setObject: a forKey: @"foo" cost: 2];
[cache setObject: b forKey: @"bar" cost: 2];
PASS_EQUAL(b, [cache objectForKey: @"bar"],
"LRU object retained on cost overflow");
PASS(nil == [cache objectForKey: @"foo"],
"Overflowing object evicted on cost overflow");
PASS([a isContentDiscarded],
"Cache did call -discardContentIfPossible on cached object");
END_SET("eviction of discardable content")
[arp release]; arp = nil;
return 0;
}