mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Add NSIndexSet
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@22474 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
b394550bf7
commit
92eb512dc6
6 changed files with 542 additions and 0 deletions
|
@ -1,3 +1,11 @@
|
|||
2006-02-12 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSIndexPath.m: new
|
||||
* Headers/Foundation/NSIndexPath.h: new
|
||||
* Headers/Foundation/Foundation.h: include NSIndexPath.h
|
||||
* Source/GNUmakefile: build NSIndexPath
|
||||
* Source/DocMakefile: document NSIndexPath
|
||||
|
||||
2006-02-10 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/win32/GSFileHandleWin32.m: Ignore extraneous write events.
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include <Foundation/NSHashTable.h>
|
||||
#include <Foundation/NSGeometry.h>
|
||||
#include <Foundation/NSHost.h>
|
||||
#include <Foundation/NSIndexPath.h>
|
||||
#include <Foundation/NSIndexSet.h>
|
||||
#include <Foundation/NSInvocation.h>
|
||||
#include <Foundation/NSKeyValueCoding.h>
|
||||
|
|
107
Headers/Foundation/NSIndexPath.h
Normal file
107
Headers/Foundation/NSIndexPath.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/** Interface for NSIndexPath for GNUStep
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
||||
Created: Feb 2006
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street,
|
||||
Fifth Floor, Boston, MA 02111 USA.
|
||||
|
||||
AutogsdocSource: NSIndexPath.m
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _NSIndexPath_h_GNUSTEP_BASE_INCLUDE
|
||||
#define _NSIndexPath_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
#if OS_API_VERSION(100400,GS_API_LATEST) && GS_API_VERSION(010200,GS_API_LATEST)
|
||||
|
||||
/**
|
||||
* Instances of this class represent a series of indexes into a hierarchy
|
||||
* of arrays.<br />
|
||||
* Each instance is a unique shared object.
|
||||
*/
|
||||
@interface NSIndexPath : NSObject <NSCopying, NSCoding>
|
||||
{
|
||||
unsigned _hash;
|
||||
unsigned _length;
|
||||
unsigned *_indexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a path containing the single value anIndex.
|
||||
*/
|
||||
+ (id) indexPathWithIndex: (unsigned)anIndex;
|
||||
|
||||
/**
|
||||
* Return a path containing all the indexes in the supplied array.
|
||||
*/
|
||||
+ (id) indexPathWithIndexes: (unsigned*)indexes length: (unsigned)length;
|
||||
|
||||
/**
|
||||
* Compares other with the receiver.<br />
|
||||
* Returns NSOrderedSame if the two are identical.<br />
|
||||
* Returns NSOrderedAscending if other is less than the receiver in a
|
||||
* depth-wise comparison.<br />
|
||||
* Returns NSOrderedDescending otherwise.
|
||||
*/
|
||||
- (NSComparisonResult) compare: (NSIndexPath*)other;
|
||||
|
||||
/**
|
||||
* Copies all index values from the receiver into aBuffer.
|
||||
*/
|
||||
- (void) getIndexes: (unsigned*)aBuffer;
|
||||
|
||||
/**
|
||||
* Return the index at the specified position or raise an exception.
|
||||
*/
|
||||
- (unsigned) indexAtPosition: (unsigned)position;
|
||||
|
||||
/**
|
||||
* Return path formed by adding anIndex to the receiver.
|
||||
*/
|
||||
- (NSIndexPath *) indexPathByAddingIndex: (unsigned)anIndex;
|
||||
|
||||
/**
|
||||
* Return path formed by removing the last index from the receiver.
|
||||
*/
|
||||
- (NSIndexPath *) indexPathByRemovingLastIndex;
|
||||
|
||||
/** <init />
|
||||
* Returns the shared instance containing the specified index, creating it
|
||||
* and destroying the receiver if necessary.
|
||||
*/
|
||||
- (id) initWithIndex: (unsigned)anIndex;
|
||||
|
||||
/** <init />
|
||||
* Returns the shared instance containing the specified index array,
|
||||
* creating it and destroying the receiver if necessary.
|
||||
*/
|
||||
- (id) initWithIndexes: (unsigned*)indexes length: (unsigned)length;
|
||||
|
||||
/**
|
||||
* Returns the number of index values present in the receiver.
|
||||
*/
|
||||
- (unsigned) length;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -63,6 +63,7 @@ NSFormatter.h \
|
|||
NSGeometry.h \
|
||||
NSHashTable.h \
|
||||
NSHost.h \
|
||||
NSIndexPath.h \
|
||||
NSIndexSet.h \
|
||||
NSInvocation.h \
|
||||
NSKeyedArchiver.h \
|
||||
|
|
|
@ -168,6 +168,7 @@ NSFormatter.m \
|
|||
NSGeometry.m \
|
||||
NSHashTable.m \
|
||||
NSHost.m \
|
||||
NSIndexPath.m \
|
||||
NSIndexSet.m \
|
||||
NSInvocation.m \
|
||||
NSKeyedArchiver.m \
|
||||
|
@ -290,6 +291,7 @@ NSFormatter.h \
|
|||
NSGeometry.h \
|
||||
NSHashTable.h \
|
||||
NSHost.h \
|
||||
NSIndexPath.h \
|
||||
NSIndexSet.h \
|
||||
NSInvocation.h \
|
||||
NSKeyedArchiver.h \
|
||||
|
|
423
Source/NSIndexPath.m
Normal file
423
Source/NSIndexPath.m
Normal file
|
@ -0,0 +1,423 @@
|
|||
/** Implementation for NSIndexPath for GNUStep
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
||||
Created: Feb 2006
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street,
|
||||
Fifth Floor, Boston, MA 02111 USA.
|
||||
|
||||
*/
|
||||
|
||||
#include <Foundation/NSByteOrder.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSHashTable.h>
|
||||
#include <Foundation/NSIndexPath.h>
|
||||
#include <Foundation/NSKeyedArchiver.h>
|
||||
#include <Foundation/NSLock.h>
|
||||
#include <Foundation/NSZone.h>
|
||||
|
||||
static NSLock *lock = nil;
|
||||
static NSHashTable *shared = 0;
|
||||
static Class myClass = 0;
|
||||
static NSIndexPath *empty = nil;
|
||||
static NSIndexPath *dummy = nil;
|
||||
|
||||
@implementation NSIndexPath
|
||||
|
||||
+ (id) allocWithZone: (NSZone*)aZone
|
||||
{
|
||||
if (self == myClass)
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
return [super allocWithZone: aZone];
|
||||
}
|
||||
|
||||
+ (id) indexPathWithIndex: (unsigned)anIndex
|
||||
{
|
||||
return [self indexPathWithIndexes: &anIndex length: 1];
|
||||
}
|
||||
|
||||
+ (id) indexPathWithIndexes: (unsigned*)indexes length: (unsigned)length
|
||||
{
|
||||
id o = [self allocWithZone: NSDefaultMallocZone()];
|
||||
|
||||
o = [o initWithIndexes: indexes length: length];
|
||||
AUTORELEASE(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (empty == nil)
|
||||
{
|
||||
myClass = self;
|
||||
empty = (NSIndexPath*)NSAllocateObject(self, 0, NSDefaultMallocZone());
|
||||
dummy = (NSIndexPath*)NSAllocateObject(self, 0, NSDefaultMallocZone());
|
||||
shared = NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 1024);
|
||||
NSHashInsert(shared, empty);
|
||||
lock = [NSLock new];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSComparisonResult) compare: (NSIndexPath*)other
|
||||
{
|
||||
if (other == self)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned pos;
|
||||
|
||||
for (pos = 0; pos < _length; pos++)
|
||||
{
|
||||
if (pos >= other->_length || other->_indexes[pos] < _indexes[pos])
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
if (other->_indexes[pos] > _indexes[pos])
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
}
|
||||
if (_length == other->_length)
|
||||
{
|
||||
/*
|
||||
* Should never get here.
|
||||
*/
|
||||
NSLog(@"Argh ... two identical index paths exist!");
|
||||
return NSOrderedSame;
|
||||
}
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)aZone
|
||||
{
|
||||
return RETAIN(self);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (self != empty)
|
||||
{
|
||||
[lock lock];
|
||||
NSHashRemove(shared, self);
|
||||
[lock unlock];
|
||||
NSZoneFree(NSDefaultMallocZone(), _indexes);
|
||||
NSDeallocateObject(self);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString*)description
|
||||
{
|
||||
NSMutableString *m = [[super description] mutableCopy];
|
||||
unsigned i;
|
||||
|
||||
[m appendFormat: @"%u indexes [", _length];
|
||||
for (i = 0; i < _length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
[m appendString: @", "];
|
||||
}
|
||||
[m appendFormat: @"%u", _indexes[i]];
|
||||
}
|
||||
[m appendString: @"]"];
|
||||
return AUTORELEASE(m);
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
if ([aCoder allowsKeyedCoding] == YES)
|
||||
{
|
||||
[aCoder encodeInt: (int)_length forKey: @"NSIndexPathLength"];
|
||||
if (_length == 1)
|
||||
{
|
||||
[aCoder encodeInt: (int)_indexes[0] forKey: @"NSIndexPathValue"];
|
||||
}
|
||||
else if (_length > 1)
|
||||
{
|
||||
NSMutableData *m;
|
||||
unsigned *buf;
|
||||
unsigned i;
|
||||
|
||||
m = [NSMutableData new];
|
||||
[m setLength: _length * sizeof(unsigned)];
|
||||
buf = [m mutableBytes];
|
||||
for (i = 0; i < _length; i++)
|
||||
{
|
||||
buf[i] = NSSwapHostIntToBig(_indexes[i]);
|
||||
}
|
||||
[aCoder encodeObject: m forKey: @"NSIndexPathData"];
|
||||
RELEASE(m);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &_length];
|
||||
if (_length > 0)
|
||||
{
|
||||
[aCoder encodeArrayOfObjCType: @encode(unsigned)
|
||||
count: _length
|
||||
at: _indexes];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) getIndexes: (unsigned*)aBuffer
|
||||
{
|
||||
memcpy(aBuffer, _indexes, _length * sizeof(unsigned));
|
||||
}
|
||||
|
||||
- (unsigned) hash
|
||||
{
|
||||
return _hash;
|
||||
}
|
||||
|
||||
- (unsigned) indexAtPosition: (unsigned)position
|
||||
{
|
||||
if (position >= _length)
|
||||
[NSException raise: NSRangeException format: @"Invalid location."];
|
||||
return _indexes[position];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return path formed by adding the index to the receiver.
|
||||
*/
|
||||
- (NSIndexPath *) indexPathByAddingIndex: (unsigned)anIndex
|
||||
{
|
||||
unsigned buffer[_length + 1];
|
||||
|
||||
[self getIndexes: buffer];
|
||||
buffer[_length] = anIndex;
|
||||
return [[self class] indexPathWithIndexes: buffer length: _length + 1];
|
||||
}
|
||||
|
||||
- (NSIndexPath *) indexPathByRemovingLastIndex
|
||||
{
|
||||
if (_length <= 1)
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return [[self class] indexPathWithIndexes: _indexes length: _length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
if ([aCoder allowsKeyedCoding] == YES)
|
||||
{
|
||||
unsigned length;
|
||||
unsigned index;
|
||||
|
||||
length = (unsigned)[aCoder decodeIntForKey: @"NSIndexPathLength"];
|
||||
if (length == 1)
|
||||
{
|
||||
index = (unsigned)[aCoder decodeIntForKey: @"NSIndexPathValue"];
|
||||
self = [self initWithIndex: index];
|
||||
}
|
||||
else if (length > 1)
|
||||
{
|
||||
// FIXME ... not MacOS-X
|
||||
NSMutableData *d = [aCoder decodeObjectForKey: @"NSIndexPathData"];
|
||||
unsigned l = [d length];
|
||||
unsigned s = l / length;
|
||||
unsigned i;
|
||||
|
||||
if (s == sizeof(unsigned))
|
||||
{
|
||||
unsigned *ptr = (unsigned*)[d mutableBytes];
|
||||
|
||||
for (i = 0; i < _length; i++)
|
||||
{
|
||||
ptr[i] = NSSwapBigIntToHost(ptr[i]);
|
||||
}
|
||||
self = [self initWithIndexes: ptr length: length];
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned *buf;
|
||||
|
||||
buf = (unsigned*)NSZoneMalloc(NSDefaultMallocZone(),
|
||||
length * sizeof(unsigned));
|
||||
if (s == sizeof(long))
|
||||
{
|
||||
long *ptr = (long*)[d mutableBytes];
|
||||
|
||||
for (i = 0; i < _length; i++)
|
||||
{
|
||||
buf[i] = (unsigned)NSSwapBigLongToHost(ptr[i]);
|
||||
}
|
||||
}
|
||||
else if (s == sizeof(short))
|
||||
{
|
||||
short *ptr = (short*)[d mutableBytes];
|
||||
|
||||
for (i = 0; i < _length; i++)
|
||||
{
|
||||
buf[i] = (unsigned)NSSwapBigShortToHost(ptr[i]);
|
||||
}
|
||||
}
|
||||
else if (s == sizeof(long long))
|
||||
{
|
||||
long long *ptr = (long long*)[d mutableBytes];
|
||||
|
||||
for (i = 0; i < _length; i++)
|
||||
{
|
||||
buf[i] = (unsigned)NSSwapBigLongLongToHost(ptr[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSGenericException format:
|
||||
@"Unable to decode unsigned integers of size %u", s];
|
||||
}
|
||||
self = [self initWithIndexes: buf length: length];
|
||||
NSZoneFree(NSDefaultMallocZone(), buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned length;
|
||||
|
||||
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &length];
|
||||
if (length == 0)
|
||||
{
|
||||
RELEASE(self);
|
||||
self = empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned buf[16];
|
||||
unsigned *indexes = buf;
|
||||
|
||||
if (length > 16)
|
||||
{
|
||||
indexes = NSZoneMalloc(NSDefaultMallocZone(),
|
||||
length * sizeof(unsigned));
|
||||
}
|
||||
[aCoder decodeArrayOfObjCType: @encode(unsigned)
|
||||
count: length
|
||||
at: indexes];
|
||||
self = [self initWithIndexes: indexes length: length];
|
||||
if (indexes != buf)
|
||||
{
|
||||
NSZoneFree(NSDefaultMallocZone(), indexes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithIndex: (unsigned)anIndex
|
||||
{
|
||||
return [self initWithIndexes: &anIndex length: 1];
|
||||
}
|
||||
|
||||
/** <init />
|
||||
* Initialise the receiver to contain the specified indexes.<br />
|
||||
* May return an existing index path.
|
||||
*/
|
||||
- (id) initWithIndexes: (unsigned*)indexes length: (unsigned)length
|
||||
{
|
||||
NSIndexPath *found;
|
||||
unsigned h = 0;
|
||||
unsigned i;
|
||||
|
||||
if (_length != 0)
|
||||
{
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Attempt to re-initialize NSIndexPath"];
|
||||
}
|
||||
// FIXME ... need better hash function?
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
h = (h << 5) ^ indexes[i];
|
||||
}
|
||||
|
||||
[lock lock];
|
||||
dummy->_hash = h;
|
||||
dummy->_length = length;
|
||||
dummy->_indexes = indexes;
|
||||
found = NSHashGet(shared, dummy);
|
||||
if (found == nil)
|
||||
{
|
||||
if (self == empty)
|
||||
{
|
||||
self = (NSIndexPath*)NSAllocateObject([self class],
|
||||
0, NSDefaultMallocZone());
|
||||
}
|
||||
_hash = dummy->_hash;
|
||||
_length = dummy->_length;
|
||||
_indexes = NSZoneMalloc(NSDefaultMallocZone(),
|
||||
_length * sizeof(unsigned));
|
||||
memcpy(_indexes, dummy->_indexes, _length * sizeof(unsigned));
|
||||
NSHashInsert(shared, self);
|
||||
}
|
||||
else
|
||||
{
|
||||
RELEASE(self);
|
||||
self = RETAIN(found);
|
||||
}
|
||||
[lock unlock];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL) isEqual: (id)other
|
||||
{
|
||||
if (other == self)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
if (other == nil || GSObjCIsKindOf(GSObjCClass(other), myClass) == NO)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
if (((NSIndexPath*)other)->_length != _length)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned *oindexes = ((NSIndexPath*)other)->_indexes;
|
||||
unsigned pos = _length;
|
||||
|
||||
while (pos-- > 0)
|
||||
{
|
||||
if (_indexes[pos] != oindexes[pos])
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (unsigned) length
|
||||
{
|
||||
return _length;
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in a new issue