1999-06-21 08:30:26 +00:00
|
|
|
/* A fast (Inline) array implementation without objc method overhead.
|
1999-04-12 12:53:30 +00:00
|
|
|
* Copyright (C) 1998,1999 Free Software Foundation, Inc.
|
|
|
|
*
|
|
|
|
* Author: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
|
|
|
* Created: Nov 1998
|
|
|
|
*
|
|
|
|
* This file is part of the GNUstep Base Library.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
1999-04-12 12:53:30 +00:00
|
|
|
* License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
* version 2 of the License, or (at your option) any later version.
|
1999-04-12 12:53:30 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
2007-09-14 11:36:11 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
1999-04-12 12:53:30 +00:00
|
|
|
* License along with this library; if not, write to the Free
|
2006-09-13 10:20:49 +00:00
|
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02111 USA. */
|
1999-04-12 12:53:30 +00:00
|
|
|
|
2006-10-31 07:05:46 +00:00
|
|
|
#import <GNUstepBase/GSVersionMacros.h>
|
|
|
|
|
2007-04-01 04:31:04 +00:00
|
|
|
#if OS_API_VERSION(GS_API_NONE,GS_API_LATEST)
|
2006-10-31 07:05:46 +00:00
|
|
|
|
2010-03-08 07:06:47 +00:00
|
|
|
|
|
|
|
#if defined(GNUSTEP_BASE_INTERNAL)
|
|
|
|
#import "Foundation/NSObject.h"
|
|
|
|
#import "Foundation/NSException.h"
|
|
|
|
#import "Foundation/NSGarbageCollector.h"
|
|
|
|
#import "Foundation/NSZone.h"
|
|
|
|
#else
|
2009-02-04 21:26:43 +00:00
|
|
|
#import <Foundation/NSObject.h>
|
|
|
|
#import <Foundation/NSException.h>
|
|
|
|
#import <Foundation/NSGarbageCollector.h>
|
|
|
|
#import <Foundation/NSZone.h>
|
2010-03-08 07:06:47 +00:00
|
|
|
#endif
|
1999-04-12 12:53:30 +00:00
|
|
|
|
2007-12-06 23:02:58 +00:00
|
|
|
/* To turn assertions on, define GSI_ARRAY_CHECKS */
|
2007-12-07 06:32:04 +00:00
|
|
|
#define GSI_ARRAY_CHECKS 1
|
2007-12-06 23:02:58 +00:00
|
|
|
|
2006-09-13 10:20:49 +00:00
|
|
|
#if defined(__cplusplus)
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
1999-04-12 12:53:30 +00:00
|
|
|
/* To easily un-inline functions for debugging */
|
2014-01-23 09:36:37 +00:00
|
|
|
#ifndef GS_STATIC_INLINE
|
|
|
|
#define GS_STATIC_INLINE static inline
|
1999-04-12 12:53:30 +00:00
|
|
|
#endif
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
|
1999-06-22 20:00:46 +00:00
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
2007-12-06 23:02:58 +00:00
|
|
|
#define GSI_ARRAY_CHECK NSCAssert(array->count <= array->cap && array->old <= array->cap, NSInternalInconsistencyException)
|
1999-06-22 20:00:46 +00:00
|
|
|
#else
|
|
|
|
#define GSI_ARRAY_CHECK
|
|
|
|
#endif
|
1999-04-12 12:53:30 +00:00
|
|
|
|
|
|
|
/*
|
2009-06-13 08:10:40 +00:00
|
|
|
* NB. This file is intended for internal use by the GNUstep libraries
|
|
|
|
* and may change siugnificantly between releases.
|
|
|
|
* While it is unlikley to be removed from the distributiuon any time
|
|
|
|
* soon, its use by other software is not officially supported.
|
|
|
|
*
|
2007-12-06 23:02:58 +00:00
|
|
|
* This file should be INCLUDED in files wanting to use the GSIArray
|
1999-04-12 12:53:30 +00:00
|
|
|
* functions - these are all declared inline for maximum performance.
|
|
|
|
*
|
|
|
|
* The file including this one may predefine some macros to alter
|
|
|
|
* the behaviour (default macros assume the items are NSObjects
|
|
|
|
* that are to be retained in the array) ...
|
|
|
|
*
|
1999-06-21 08:30:26 +00:00
|
|
|
* GSI_ARRAY_RETAIN()
|
1999-04-12 12:53:30 +00:00
|
|
|
* Macro to retain an array item
|
|
|
|
*
|
1999-06-21 08:30:26 +00:00
|
|
|
* GSI_ARRAY_RELEASE()
|
1999-04-12 12:53:30 +00:00
|
|
|
* Macro to release the item.
|
|
|
|
*
|
|
|
|
* The next two values can be defined in order to let us optimise
|
|
|
|
* even further when either retain or release operations are not needed.
|
|
|
|
*
|
1999-06-21 08:30:26 +00:00
|
|
|
* GSI_ARRAY_NO_RELEASE
|
1999-04-12 12:53:30 +00:00
|
|
|
* Defined if no release operation is needed for an item
|
1999-06-21 08:30:26 +00:00
|
|
|
* GSI_ARRAY_NO_RETAIN
|
1999-04-12 12:53:30 +00:00
|
|
|
* Defined if no retain operation is needed for a an item
|
2002-01-31 07:20:16 +00:00
|
|
|
*
|
|
|
|
* The value GSI_ARRAY_EXTRA may be defined as the type of an extra
|
|
|
|
* field produced in every array. The name of this field is 'extra'.
|
|
|
|
*
|
2002-01-31 07:24:27 +00:00
|
|
|
* The value GSI_ARRAY_TYPE may be defined as an additional type
|
2002-01-31 07:20:16 +00:00
|
|
|
* which must be valid as an array element. Otherwise the types are
|
|
|
|
* controlled by the mechanism in GSUnion.h
|
1999-04-20 16:28:04 +00:00
|
|
|
*/
|
2002-01-31 07:20:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef GSI_ARRAY_NO_RETAIN
|
|
|
|
#ifdef GSI_ARRAY_RETAIN
|
|
|
|
#undef GSI_ARRAY_RETAIN
|
|
|
|
#endif
|
|
|
|
#define GSI_ARRAY_RETAIN(A, X)
|
|
|
|
#else
|
|
|
|
#ifndef GSI_ARRAY_RETAIN
|
|
|
|
#define GSI_ARRAY_RETAIN(A, X) [(X).obj retain]
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef GSI_ARRAY_NO_RELEASE
|
|
|
|
#ifdef GSI_ARRAY_RELEASE
|
|
|
|
#undef GSI_ARRAY_RELEASE
|
|
|
|
#endif
|
|
|
|
#define GSI_ARRAY_RELEASE(A, X)
|
|
|
|
#else
|
|
|
|
#ifndef GSI_ARRAY_RELEASE
|
|
|
|
#define GSI_ARRAY_RELEASE(A, X) [(X).obj release]
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
1999-04-12 12:53:30 +00:00
|
|
|
/*
|
|
|
|
* If there is no bitmask defined to supply the types that
|
2009-10-02 14:41:25 +00:00
|
|
|
* may be stored in the array, default to none.
|
1999-04-12 12:53:30 +00:00
|
|
|
*/
|
1999-06-21 08:30:26 +00:00
|
|
|
#ifndef GSI_ARRAY_TYPES
|
2009-10-02 14:41:25 +00:00
|
|
|
#define GSI_ARRAY_TYPES 0
|
1999-04-12 12:53:30 +00:00
|
|
|
#endif
|
|
|
|
|
2007-04-05 08:42:40 +00:00
|
|
|
#ifndef GSIArrayItem
|
|
|
|
|
1999-04-12 12:53:30 +00:00
|
|
|
/*
|
|
|
|
* Set up the name of the union to store array elements.
|
|
|
|
*/
|
|
|
|
#ifdef GSUNION
|
|
|
|
#undef GSUNION
|
|
|
|
#endif
|
1999-06-21 08:30:26 +00:00
|
|
|
#define GSUNION GSIArrayItem
|
1999-04-12 12:53:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the types that will be storable in the union.
|
|
|
|
* See 'GSUnion.h' for details.
|
|
|
|
*/
|
|
|
|
#ifdef GSUNION_TYPES
|
|
|
|
#undef GSUNION_TYPES
|
|
|
|
#endif
|
1999-06-21 08:30:26 +00:00
|
|
|
#define GSUNION_TYPES GSI_ARRAY_TYPES
|
1999-04-12 12:53:30 +00:00
|
|
|
#ifdef GSUNION_EXTRA
|
|
|
|
#undef GSUNION_EXTRA
|
|
|
|
#endif
|
2002-01-31 07:24:27 +00:00
|
|
|
|
2002-01-31 07:20:16 +00:00
|
|
|
/*
|
|
|
|
* Override extra type used in array value
|
|
|
|
*/
|
2002-01-31 07:24:27 +00:00
|
|
|
#ifdef GSI_ARRAY_TYPE
|
|
|
|
#define GSUNION_EXTRA GSI_ARRAY_TYPE
|
|
|
|
#endif
|
|
|
|
|
1999-04-12 12:53:30 +00:00
|
|
|
/*
|
|
|
|
* Generate the union typedef
|
|
|
|
*/
|
2010-03-08 07:06:47 +00:00
|
|
|
#if defined(GNUSTEP_BASE_INTERNAL)
|
|
|
|
#include "GNUstepBase/GSUnion.h"
|
|
|
|
#else
|
2003-07-31 23:49:32 +00:00
|
|
|
#include <GNUstepBase/GSUnion.h>
|
2010-03-08 07:06:47 +00:00
|
|
|
#endif
|
1999-04-12 12:53:30 +00:00
|
|
|
|
2007-04-05 08:42:40 +00:00
|
|
|
#endif /* #ifndef GSIArrayItem */
|
|
|
|
|
1999-06-21 08:30:26 +00:00
|
|
|
struct _GSIArray {
|
|
|
|
GSIArrayItem *ptr;
|
1999-04-12 12:53:30 +00:00
|
|
|
unsigned count;
|
|
|
|
unsigned cap;
|
|
|
|
unsigned old;
|
|
|
|
NSZone *zone;
|
2002-01-31 07:20:16 +00:00
|
|
|
#ifdef GSI_ARRAY_EXTRA
|
|
|
|
GSI_ARRAY_EXTRA extra;
|
|
|
|
#endif
|
1999-04-12 12:53:30 +00:00
|
|
|
};
|
1999-06-21 08:30:26 +00:00
|
|
|
typedef struct _GSIArray GSIArray_t;
|
|
|
|
typedef struct _GSIArray *GSIArray;
|
1999-04-12 12:53:30 +00:00
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE unsigned
|
2001-01-12 11:40:20 +00:00
|
|
|
GSIArrayCapacity(GSIArray array)
|
|
|
|
{
|
|
|
|
return array->cap;
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE unsigned
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayCount(GSIArray array)
|
1999-04-21 20:16:25 +00:00
|
|
|
{
|
|
|
|
return array->count;
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayGrow(GSIArray array)
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int next;
|
|
|
|
unsigned int size;
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayItem *tmp;
|
1999-04-20 16:28:04 +00:00
|
|
|
|
2004-03-31 13:23:38 +00:00
|
|
|
if (array->old == 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Statically initialised buffer ... copy into new heap buffer.
|
|
|
|
*/
|
|
|
|
array->old = array->cap / 2;
|
|
|
|
if (array->old < 1)
|
|
|
|
{
|
|
|
|
array->old = 1;
|
2008-10-31 10:47:08 +00:00
|
|
|
array->cap = 1;
|
2004-03-31 13:23:38 +00:00
|
|
|
}
|
|
|
|
next = array->cap + array->old;
|
|
|
|
size = next*sizeof(GSIArrayItem);
|
2009-03-09 15:11:51 +00:00
|
|
|
tmp = NSZoneMalloc(array->zone, size);
|
2004-03-31 13:23:38 +00:00
|
|
|
memcpy(tmp, array->ptr, array->count * sizeof(GSIArrayItem));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
next = array->cap + array->old;
|
|
|
|
size = next*sizeof(GSIArrayItem);
|
2009-03-09 15:11:51 +00:00
|
|
|
tmp = NSZoneRealloc(array->zone, array->ptr, size);
|
2004-03-31 13:23:38 +00:00
|
|
|
}
|
1999-04-20 16:28:04 +00:00
|
|
|
|
|
|
|
if (tmp == 0)
|
|
|
|
{
|
|
|
|
[NSException raise: NSMallocException
|
1999-06-21 08:30:26 +00:00
|
|
|
format: @"failed to grow GSIArray"];
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
|
|
|
array->ptr = tmp;
|
|
|
|
array->old = array->cap;
|
|
|
|
array->cap = next;
|
|
|
|
}
|
1999-04-12 12:53:30 +00:00
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
2001-01-12 11:40:20 +00:00
|
|
|
GSIArrayGrowTo(GSIArray array, unsigned next)
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int size;
|
2001-01-12 11:40:20 +00:00
|
|
|
GSIArrayItem *tmp;
|
|
|
|
|
|
|
|
if (next < array->count)
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"attempt to shrink below count"];
|
|
|
|
}
|
|
|
|
size = next*sizeof(GSIArrayItem);
|
2008-10-31 10:47:08 +00:00
|
|
|
if (array->old == 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Statically initialised buffer ... copy into new heap buffer.
|
|
|
|
*/
|
2009-03-09 15:11:51 +00:00
|
|
|
tmp = NSZoneMalloc(array->zone, size);
|
2008-10-31 10:47:08 +00:00
|
|
|
memcpy(tmp, array->ptr, array->count * sizeof(GSIArrayItem));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-03-09 15:11:51 +00:00
|
|
|
tmp = NSZoneRealloc(array->zone, array->ptr, size);
|
2008-10-31 10:47:08 +00:00
|
|
|
}
|
2001-01-12 11:40:20 +00:00
|
|
|
|
|
|
|
if (tmp == 0)
|
|
|
|
{
|
|
|
|
[NSException raise: NSMallocException
|
|
|
|
format: @"failed to grow GSIArray"];
|
|
|
|
}
|
|
|
|
array->ptr = tmp;
|
2008-10-31 10:54:09 +00:00
|
|
|
array->old = (array->cap > 0 ? array->cap : 1);
|
2001-01-12 11:40:20 +00:00
|
|
|
array->cap = next;
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayInsertItem(GSIArray array, GSIArrayItem item, unsigned index)
|
1999-04-12 12:53:30 +00:00
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
1999-04-20 16:28:04 +00:00
|
|
|
|
1999-06-21 08:30:26 +00:00
|
|
|
GSI_ARRAY_CHECK;
|
2008-10-31 10:57:59 +00:00
|
|
|
GSI_ARRAY_RETAIN(array, item);
|
1999-04-12 12:53:30 +00:00
|
|
|
if (array->count == array->cap)
|
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayGrow(array);
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
1999-04-22 11:58:53 +00:00
|
|
|
for (i = array->count++; i > index; i--)
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
|
|
|
array->ptr[i] = array->ptr[i-1];
|
|
|
|
}
|
|
|
|
array->ptr[i] = item;
|
1999-06-21 08:30:26 +00:00
|
|
|
GSI_ARRAY_CHECK;
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
1999-04-12 12:53:30 +00:00
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayInsertItemNoRetain(GSIArray array, GSIArrayItem item, unsigned index)
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
1999-04-12 12:53:30 +00:00
|
|
|
|
1999-06-21 08:30:26 +00:00
|
|
|
GSI_ARRAY_CHECK;
|
1999-04-20 16:28:04 +00:00
|
|
|
if (array->count == array->cap)
|
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayGrow(array);
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
1999-04-22 11:58:53 +00:00
|
|
|
for (i = array->count++; i > index; i--)
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
|
|
|
array->ptr[i] = array->ptr[i-1];
|
|
|
|
}
|
|
|
|
array->ptr[i] = item;
|
1999-06-21 08:30:26 +00:00
|
|
|
GSI_ARRAY_CHECK;
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayAddItem(GSIArray array, GSIArrayItem item)
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
GSI_ARRAY_CHECK;
|
2008-10-31 10:57:59 +00:00
|
|
|
GSI_ARRAY_RETAIN(array, item);
|
1999-04-20 16:28:04 +00:00
|
|
|
if (array->count == array->cap)
|
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayGrow(array);
|
1999-04-12 12:53:30 +00:00
|
|
|
}
|
|
|
|
array->ptr[array->count++] = item;
|
1999-06-21 08:30:26 +00:00
|
|
|
GSI_ARRAY_CHECK;
|
1999-04-12 12:53:30 +00:00
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayAddItemNoRetain(GSIArray array, GSIArrayItem item)
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
GSI_ARRAY_CHECK;
|
1999-04-20 16:28:04 +00:00
|
|
|
if (array->count == array->cap)
|
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayGrow(array);
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
|
|
|
array->ptr[array->count++] = item;
|
1999-06-21 08:30:26 +00:00
|
|
|
GSI_ARRAY_CHECK;
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The comparator function takes two items as arguments, the first is the
|
|
|
|
* item to be added, the second is the item already in the array.
|
1999-04-28 23:02:15 +00:00
|
|
|
* The function should return NSOrderedAscending if the item to be
|
|
|
|
* added is 'less than' the item in the array, NSOrderedDescending
|
|
|
|
* if it is greater, and NSOrderedSame if it is equal.
|
1999-04-20 16:28:04 +00:00
|
|
|
*/
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE unsigned
|
2007-04-05 08:42:40 +00:00
|
|
|
GSIArraySearch(GSIArray array, GSIArrayItem item,
|
2007-12-06 23:02:58 +00:00
|
|
|
NSComparisonResult (*sorter)(GSIArrayItem, GSIArrayItem))
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int upper = array->count;
|
|
|
|
unsigned int lower = 0;
|
|
|
|
unsigned int index;
|
1999-04-20 16:28:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Binary search for an item equal to the one to be inserted.
|
2007-04-05 08:42:40 +00:00
|
|
|
* Only for sorted array !
|
1999-04-21 20:16:25 +00:00
|
|
|
*/
|
2002-09-08 08:53:35 +00:00
|
|
|
for (index = upper/2; upper != lower; index = (upper+lower)/2)
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
1999-04-28 23:02:15 +00:00
|
|
|
NSComparisonResult comparison;
|
1999-04-20 16:28:04 +00:00
|
|
|
|
1999-04-28 23:02:15 +00:00
|
|
|
comparison = (*sorter)(item, (array->ptr[index]));
|
|
|
|
if (comparison == NSOrderedAscending)
|
|
|
|
{
|
|
|
|
upper = index;
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
1999-04-28 23:02:15 +00:00
|
|
|
else if (comparison == NSOrderedDescending)
|
|
|
|
{
|
|
|
|
lower = index + 1;
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
|
|
|
else
|
1999-04-28 23:02:15 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
2007-04-05 08:42:40 +00:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE unsigned
|
2007-04-05 08:42:40 +00:00
|
|
|
GSIArrayInsertionPosition(GSIArray array, GSIArrayItem item,
|
2007-12-06 23:02:58 +00:00
|
|
|
NSComparisonResult (*sorter)(GSIArrayItem, GSIArrayItem))
|
2007-04-05 08:42:40 +00:00
|
|
|
{
|
|
|
|
unsigned int index;
|
|
|
|
|
|
|
|
index = GSIArraySearch(array,item,sorter);
|
1999-04-20 16:28:04 +00:00
|
|
|
/*
|
|
|
|
* Now skip past any equal items so the insertion point is AFTER any
|
|
|
|
* items that are equal to the new one.
|
|
|
|
*/
|
1999-04-28 23:02:15 +00:00
|
|
|
while (index < array->count
|
|
|
|
&& (*sorter)(item, (array->ptr[index])) != NSOrderedAscending)
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
|
|
|
index++;
|
|
|
|
}
|
1999-06-22 20:00:46 +00:00
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
1999-04-21 20:16:25 +00:00
|
|
|
NSCAssert(index <= array->count, NSInternalInconsistencyException);
|
1999-06-22 20:00:46 +00:00
|
|
|
#endif
|
1999-04-20 16:28:04 +00:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
1999-06-22 20:00:46 +00:00
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayCheckSort(GSIArray array,
|
2007-12-06 23:02:58 +00:00
|
|
|
NSComparisonResult (*sorter)(GSIArrayItem, GSIArrayItem))
|
1999-04-21 20:16:25 +00:00
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
1999-04-21 20:16:25 +00:00
|
|
|
|
1999-04-22 11:58:53 +00:00
|
|
|
for (i = 1; i < array->count; i++)
|
1999-04-21 20:16:25 +00:00
|
|
|
{
|
1999-06-22 20:00:46 +00:00
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
1999-04-28 23:02:15 +00:00
|
|
|
NSCAssert(((*sorter)(array->ptr[i-1], array->ptr[i])
|
2007-12-06 23:02:58 +00:00
|
|
|
!= NSOrderedDescending), NSInvalidArgumentException);
|
1999-06-22 20:00:46 +00:00
|
|
|
#endif
|
1999-04-21 20:16:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayInsertSorted(GSIArray array, GSIArrayItem item,
|
2007-12-06 23:02:58 +00:00
|
|
|
NSComparisonResult (*sorter)(GSIArrayItem, GSIArrayItem))
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int index;
|
1999-04-20 16:28:04 +00:00
|
|
|
|
2007-12-06 23:02:58 +00:00
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
|
|
|
GSIArrayCheckSort(array, sorter);
|
|
|
|
#endif
|
1999-06-21 08:30:26 +00:00
|
|
|
index = GSIArrayInsertionPosition(array, item, sorter);
|
|
|
|
GSIArrayInsertItem(array, item, index);
|
1999-06-22 20:00:46 +00:00
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayCheckSort(array, sorter);
|
1999-04-21 20:16:25 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayInsertSortedNoRetain(GSIArray array, GSIArrayItem item,
|
2007-12-06 23:02:58 +00:00
|
|
|
NSComparisonResult (*sorter)(GSIArrayItem, GSIArrayItem))
|
1999-04-21 20:16:25 +00:00
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int index;
|
1999-04-21 20:16:25 +00:00
|
|
|
|
2007-12-06 23:02:58 +00:00
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
|
|
|
GSIArrayCheckSort(array, sorter);
|
|
|
|
#endif
|
1999-06-21 08:30:26 +00:00
|
|
|
index = GSIArrayInsertionPosition(array, item, sorter);
|
|
|
|
GSIArrayInsertItemNoRetain(array, item, index);
|
1999-06-22 20:00:46 +00:00
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayCheckSort(array, sorter);
|
1999-04-21 20:16:25 +00:00
|
|
|
#endif
|
1999-04-20 16:28:04 +00:00
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayRemoveItemAtIndex(GSIArray array, unsigned index)
|
1999-04-12 12:53:30 +00:00
|
|
|
{
|
2011-03-13 08:20:17 +00:00
|
|
|
#if defined(GSI_ARRAY_NO_RELEASE)
|
|
|
|
# ifdef GSI_ARRAY_CHECKS
|
|
|
|
NSCAssert(index < array->count, NSInvalidArgumentException);
|
|
|
|
# endif
|
|
|
|
while (++index < array->count)
|
|
|
|
array->ptr[index-1] = array->ptr[index];
|
|
|
|
array->count--;
|
|
|
|
#else
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayItem tmp;
|
2011-03-13 08:20:17 +00:00
|
|
|
# ifdef GSI_ARRAY_CHECKS
|
1999-04-12 12:53:30 +00:00
|
|
|
NSCAssert(index < array->count, NSInvalidArgumentException);
|
2011-03-13 08:20:17 +00:00
|
|
|
# endif
|
1999-04-12 12:53:30 +00:00
|
|
|
tmp = array->ptr[index];
|
|
|
|
while (++index < array->count)
|
|
|
|
array->ptr[index-1] = array->ptr[index];
|
|
|
|
array->count--;
|
2002-01-31 07:20:16 +00:00
|
|
|
GSI_ARRAY_RELEASE(array, tmp);
|
2009-03-10 11:30:16 +00:00
|
|
|
#endif
|
1999-04-12 12:53:30 +00:00
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-24 19:23:09 +00:00
|
|
|
GSIArrayRemoveLastItem(GSIArray array)
|
|
|
|
{
|
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
|
|
|
NSCAssert(array->count, NSInvalidArgumentException);
|
|
|
|
#endif
|
|
|
|
array->count--;
|
2011-03-13 08:20:17 +00:00
|
|
|
#if !defined(GSI_ARRAY_NO_RELEASE)
|
2009-03-10 11:30:16 +00:00
|
|
|
GSI_ARRAY_RELEASE(array, array->ptr[array->count]);
|
|
|
|
#endif
|
1999-06-24 19:23:09 +00:00
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayRemoveItemAtIndexNoRelease(GSIArray array, unsigned index)
|
1999-04-20 16:28:04 +00:00
|
|
|
{
|
1999-06-22 20:00:46 +00:00
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
1999-04-20 16:28:04 +00:00
|
|
|
NSCAssert(index < array->count, NSInvalidArgumentException);
|
1999-06-22 20:00:46 +00:00
|
|
|
#endif
|
1999-04-20 16:28:04 +00:00
|
|
|
while (++index < array->count)
|
|
|
|
array->ptr[index-1] = array->ptr[index];
|
|
|
|
array->count--;
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArraySetItemAtIndex(GSIArray array, GSIArrayItem item, unsigned index)
|
1999-04-12 12:53:30 +00:00
|
|
|
{
|
2011-03-13 08:20:17 +00:00
|
|
|
#if defined(GSI_ARRAY_NO_RELEASE)
|
|
|
|
# ifdef GSI_ARRAY_CHECKS
|
|
|
|
NSCAssert(index < array->count, NSInvalidArgumentException);
|
|
|
|
# endif
|
|
|
|
GSI_ARRAY_RETAIN(array, item);
|
|
|
|
array->ptr[index] = item;
|
|
|
|
#else
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayItem tmp;
|
2011-03-13 08:20:17 +00:00
|
|
|
# ifdef GSI_ARRAY_CHECKS
|
1999-04-12 12:53:30 +00:00
|
|
|
NSCAssert(index < array->count, NSInvalidArgumentException);
|
2011-03-13 08:20:17 +00:00
|
|
|
# endif
|
1999-04-12 12:53:30 +00:00
|
|
|
tmp = array->ptr[index];
|
2002-01-31 07:20:16 +00:00
|
|
|
GSI_ARRAY_RETAIN(array, item);
|
1999-04-12 12:53:30 +00:00
|
|
|
array->ptr[index] = item;
|
2002-01-31 07:20:16 +00:00
|
|
|
GSI_ARRAY_RELEASE(array, tmp);
|
2011-03-13 08:20:17 +00:00
|
|
|
#endif
|
1999-04-12 12:53:30 +00:00
|
|
|
}
|
|
|
|
|
2002-02-22 11:13:45 +00:00
|
|
|
/*
|
|
|
|
* For direct access ... unsafe if you change the array in any way while
|
|
|
|
* examining the contents of this buffer.
|
|
|
|
*/
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE GSIArrayItem *
|
2002-02-22 11:13:45 +00:00
|
|
|
GSIArrayItems(GSIArray array)
|
|
|
|
{
|
|
|
|
return array->ptr;
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE GSIArrayItem
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayItemAtIndex(GSIArray array, unsigned index)
|
1999-04-12 12:53:30 +00:00
|
|
|
{
|
1999-06-22 20:00:46 +00:00
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
1999-04-12 12:53:30 +00:00
|
|
|
NSCAssert(index < array->count, NSInvalidArgumentException);
|
1999-06-22 20:00:46 +00:00
|
|
|
#endif
|
1999-04-12 12:53:30 +00:00
|
|
|
return array->ptr[index];
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE GSIArrayItem
|
1999-06-24 19:23:09 +00:00
|
|
|
GSIArrayLastItem(GSIArray array)
|
|
|
|
{
|
|
|
|
#ifdef GSI_ARRAY_CHECKS
|
|
|
|
NSCAssert(array->count, NSInvalidArgumentException);
|
|
|
|
#endif
|
|
|
|
return array->ptr[array->count-1];
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayClear(GSIArray array)
|
1999-04-12 12:53:30 +00:00
|
|
|
{
|
|
|
|
if (array->ptr)
|
|
|
|
{
|
2004-03-31 13:23:38 +00:00
|
|
|
/*
|
|
|
|
* Only free memory if it was dynamically initialised (old > 0)
|
|
|
|
*/
|
|
|
|
if (array->old > 0)
|
|
|
|
{
|
|
|
|
NSZoneFree(array->zone, (void*)array->ptr);
|
|
|
|
}
|
1999-04-12 12:53:30 +00:00
|
|
|
array->ptr = 0;
|
|
|
|
array->cap = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayRemoveItemsFromIndex(GSIArray array, unsigned index)
|
1999-04-12 12:53:30 +00:00
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
if (index < array->count)
|
|
|
|
{
|
|
|
|
#ifndef GSI_ARRAY_NO_RELEASE
|
|
|
|
while (array->count-- > index)
|
|
|
|
{
|
2002-01-31 07:20:16 +00:00
|
|
|
GSI_ARRAY_RELEASE(array, array->ptr[array->count]);
|
1999-06-21 08:30:26 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
array->count = index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayRemoveAllItems(GSIArray array)
|
|
|
|
{
|
|
|
|
#ifndef GSI_ARRAY_NO_RELEASE
|
1999-04-12 12:53:30 +00:00
|
|
|
while (array->count--)
|
|
|
|
{
|
2002-01-31 07:20:16 +00:00
|
|
|
GSI_ARRAY_RELEASE(array, array->ptr[array->count]);
|
1999-04-12 12:53:30 +00:00
|
|
|
}
|
|
|
|
#endif
|
1999-06-20 08:34:00 +00:00
|
|
|
array->count = 0;
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE void
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayEmpty(GSIArray array)
|
1999-06-20 08:34:00 +00:00
|
|
|
{
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayRemoveAllItems(array);
|
|
|
|
GSIArrayClear(array);
|
1999-04-12 12:53:30 +00:00
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE GSIArray
|
1999-06-21 08:30:26 +00:00
|
|
|
GSIArrayInitWithZoneAndCapacity(GSIArray array, NSZone *zone, size_t capacity)
|
1999-04-12 12:53:30 +00:00
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int size;
|
1999-04-12 12:53:30 +00:00
|
|
|
|
2009-03-09 15:11:51 +00:00
|
|
|
array->zone = zone;
|
1999-04-12 12:53:30 +00:00
|
|
|
array->count = 0;
|
|
|
|
if (capacity < 2)
|
|
|
|
capacity = 2;
|
|
|
|
array->cap = capacity;
|
|
|
|
array->old = capacity/2;
|
1999-06-21 08:30:26 +00:00
|
|
|
size = capacity*sizeof(GSIArrayItem);
|
2009-03-09 15:11:51 +00:00
|
|
|
array->ptr = (GSIArrayItem*)NSZoneMalloc(zone, size);
|
1999-04-12 12:53:30 +00:00
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE GSIArray
|
2004-03-31 13:23:38 +00:00
|
|
|
GSIArrayInitWithZoneAndStaticCapacity(GSIArray array, NSZone *zone,
|
|
|
|
size_t capacity, GSIArrayItem *buffer)
|
|
|
|
{
|
2009-03-09 15:11:51 +00:00
|
|
|
array->zone = zone;
|
2004-03-31 13:23:38 +00:00
|
|
|
array->count = 0;
|
|
|
|
array->cap = capacity;
|
|
|
|
array->old = 0;
|
|
|
|
array->ptr = buffer;
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
2014-01-23 09:36:37 +00:00
|
|
|
GS_STATIC_INLINE GSIArray
|
1999-06-24 19:23:09 +00:00
|
|
|
GSIArrayCopyWithZone(GSIArray array, NSZone *zone)
|
|
|
|
{
|
2003-01-03 20:14:47 +00:00
|
|
|
unsigned int i;
|
1999-06-24 19:23:09 +00:00
|
|
|
GSIArray new;
|
2009-02-04 21:26:43 +00:00
|
|
|
|
2009-03-09 15:11:51 +00:00
|
|
|
new = NSZoneMalloc(zone, sizeof(GSIArray_t));
|
|
|
|
GSIArrayInitWithZoneAndCapacity(new, zone, array->count);
|
1999-06-24 19:23:09 +00:00
|
|
|
for (i = 0; i < array->count; i++)
|
|
|
|
{
|
2002-01-31 07:20:16 +00:00
|
|
|
GSI_ARRAY_RETAIN(array, array->ptr[i]);
|
1999-06-24 19:23:09 +00:00
|
|
|
new->ptr[new->count++] = array->ptr[i];
|
|
|
|
}
|
|
|
|
return new;
|
|
|
|
}
|
2006-09-13 10:20:49 +00:00
|
|
|
|
|
|
|
#if defined(__cplusplus)
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-10-31 07:05:46 +00:00
|
|
|
#endif /* OS_API_VERSION(GS_API_NONE,GS_API_NONE) */
|
|
|
|
|