forked from KolibriOS/kolibrios
Clib string & memory functions
git-svn-id: svn://kolibrios.org@553 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
83
programs/develop/open watcom/trunk/clib/search/bsearch.c
Normal file
83
programs/develop/open watcom/trunk/clib/search/bsearch.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Open Watcom Project
|
||||
*
|
||||
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original
|
||||
* Code as defined in and that are subject to the Sybase Open Watcom
|
||||
* Public License version 1.0 (the 'License'). You may not use this file
|
||||
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||||
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||||
* provided with the Original Code and Modifications, and is also
|
||||
* available at www.sybase.com/developer/opensource.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||||
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||||
* NON-INFRINGEMENT. Please see the License for the specific language
|
||||
* governing rights and limitations under the License.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
|
||||
* DESCRIBE IT HERE!
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "variety.h"
|
||||
#undef __INLINE_FUNCTIONS__
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "extfunc.h"
|
||||
|
||||
/*
|
||||
The old bsearch could SIGSEGV if the compare is done on elements
|
||||
which are not within the given segment. The error occurs if the search
|
||||
key is larger than the 'high' element (or lower than the 'low' member)
|
||||
and 'low','mid' and 'high' are all equal (either from the start or
|
||||
after several iterations).
|
||||
*/
|
||||
|
||||
typedef int bcomp();
|
||||
#if defined(_M_IX86)
|
||||
#pragma aux (__outside_CLIB) bcomp;
|
||||
#endif
|
||||
|
||||
_WCRTLINK void * bsearch( const void * key,
|
||||
const void * base,
|
||||
size_t nmemb,
|
||||
size_t size,
|
||||
int (*cmp)() )
|
||||
{
|
||||
char *low;
|
||||
char *high;
|
||||
char *mid;
|
||||
int cond;
|
||||
bcomp *compar = cmp;
|
||||
|
||||
if( nmemb == 0 ) {
|
||||
return( NULL );
|
||||
}
|
||||
low = (char *) base;
|
||||
high = low + (nmemb-1) * size;
|
||||
// JBS while( low <= high ) {
|
||||
while( low < high ) {
|
||||
mid = low + ( (high-low)/size/2 ) * size;
|
||||
cond = (*compar)( key, mid );
|
||||
if( cond == 0 ) return( mid );
|
||||
if( cond < 0 ) { /* key < mid */
|
||||
// JBS high = mid - size;
|
||||
high = mid;
|
||||
} else { /* key > mid */
|
||||
low = mid + size;
|
||||
}
|
||||
}
|
||||
if (low == high) return( (*compar)(key, low) ? NULL : low );
|
||||
return( NULL );
|
||||
}
|
84
programs/develop/open watcom/trunk/clib/search/bsrch_s.c
Normal file
84
programs/develop/open watcom/trunk/clib/search/bsrch_s.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Open Watcom Project
|
||||
*
|
||||
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original
|
||||
* Code as defined in and that are subject to the Sybase Open Watcom
|
||||
* Public License version 1.0 (the 'License'). You may not use this file
|
||||
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||||
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||||
* provided with the Original Code and Modifications, and is also
|
||||
* available at www.sybase.com/developer/opensource.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||||
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||||
* NON-INFRINGEMENT. Please see the License for the specific language
|
||||
* governing rights and limitations under the License.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Description: Implementation of bsearch_s() - bounds-checking bsearch().
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "variety.h"
|
||||
#include "saferlib.h"
|
||||
#undef __INLINE_FUNCTIONS__
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "extfunc.h"
|
||||
|
||||
typedef int bcomp();
|
||||
#ifdef _M_IX86
|
||||
#pragma aux (__outside_CLIB) bcomp;
|
||||
#endif
|
||||
|
||||
_WCRTLINK void * bsearch_s( const void * key, const void * base,
|
||||
rsize_t nmemb, rsize_t size,
|
||||
int (*compar)( const void *k, const void *y, void *context ),
|
||||
void *context )
|
||||
/***********************************************************************/
|
||||
{
|
||||
char *low;
|
||||
char *high;
|
||||
char *mid;
|
||||
int cond;
|
||||
bcomp *comp = compar;
|
||||
|
||||
/* runtime-constraints */
|
||||
// nmemb <= RSIZE_MAX
|
||||
// size <= RSIZE_MAX
|
||||
// if nmemb > 0 then key, base, compar not NULL
|
||||
if( __check_constraint_maxsize( nmemb ) &&
|
||||
__check_constraint_maxsize( size ) &&
|
||||
( (nmemb == 0) || __check_constraint_nullptr( key ) &&
|
||||
__check_constraint_nullptr( base ) &&
|
||||
__check_constraint_nullptr( compar )) ) {
|
||||
|
||||
if( nmemb == 0 ) { /* empty array - nothing to do */
|
||||
return( NULL );
|
||||
}
|
||||
low = (char *) base;
|
||||
high = low + (nmemb - 1) * size;
|
||||
while( low < high ) {
|
||||
mid = low + ( (high - low) / size / 2 ) * size;
|
||||
cond = (*comp)( key, mid, context );
|
||||
if( cond == 0 ) return( mid );
|
||||
if( cond < 0 ) { /* key < mid */
|
||||
high = mid;
|
||||
} else { /* key > mid */
|
||||
low = mid + size;
|
||||
}
|
||||
}
|
||||
if (low == high) return( (*comp)( key, low, context ) ? NULL : low );
|
||||
}
|
||||
return( NULL );
|
||||
}
|
65
programs/develop/open watcom/trunk/clib/search/lfind.c
Normal file
65
programs/develop/open watcom/trunk/clib/search/lfind.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Open Watcom Project
|
||||
*
|
||||
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original
|
||||
* Code as defined in and that are subject to the Sybase Open Watcom
|
||||
* Public License version 1.0 (the 'License'). You may not use this file
|
||||
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||||
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||||
* provided with the Original Code and Modifications, and is also
|
||||
* available at www.sybase.com/developer/opensource.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||||
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||||
* NON-INFRINGEMENT. Please see the License for the specific language
|
||||
* governing rights and limitations under the License.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
|
||||
* DESCRIBE IT HERE!
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "variety.h"
|
||||
#include "extfunc.h"
|
||||
#undef __INLINE_FUNCTIONS__
|
||||
#include <stddef.h>
|
||||
#include <search.h>
|
||||
|
||||
typedef int lcomp( const void *, const void * );
|
||||
#if defined(_M_IX86)
|
||||
#pragma aux (__outside_CLIB) lcomp;
|
||||
#endif
|
||||
|
||||
_WCRTLINK void *lfind(
|
||||
const void *key,
|
||||
const void *base,
|
||||
unsigned *num,
|
||||
unsigned width,
|
||||
int (*compare)(
|
||||
const void *,
|
||||
const void *
|
||||
)
|
||||
)
|
||||
{
|
||||
lcomp *cmp = (lcomp *)compare;
|
||||
unsigned n;
|
||||
|
||||
for( n = *num; n; --n )
|
||||
{
|
||||
if( cmp( key, base ) == 0 )
|
||||
return( (void *)base );
|
||||
base = ((const char *)base) + width;
|
||||
}
|
||||
return( NULL );
|
||||
}
|
68
programs/develop/open watcom/trunk/clib/search/lsearch.c
Normal file
68
programs/develop/open watcom/trunk/clib/search/lsearch.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Open Watcom Project
|
||||
*
|
||||
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original
|
||||
* Code as defined in and that are subject to the Sybase Open Watcom
|
||||
* Public License version 1.0 (the 'License'). You may not use this file
|
||||
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||||
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||||
* provided with the Original Code and Modifications, and is also
|
||||
* available at www.sybase.com/developer/opensource.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||||
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||||
* NON-INFRINGEMENT. Please see the License for the specific language
|
||||
* governing rights and limitations under the License.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
|
||||
* DESCRIBE IT HERE!
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "variety.h"
|
||||
#include "extfunc.h"
|
||||
#undef __INLINE_FUNCTIONS__
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <search.h>
|
||||
|
||||
typedef int lcomp( const void *, const void * );
|
||||
#if defined(_M_IX86)
|
||||
#pragma aux (__outside_CLIB) lcomp;
|
||||
#endif
|
||||
|
||||
_WCRTLINK void *lsearch(
|
||||
const void *key,
|
||||
void *base,
|
||||
unsigned *num,
|
||||
unsigned width,
|
||||
int (*compare)(
|
||||
const void *,
|
||||
const void *
|
||||
)
|
||||
)
|
||||
{
|
||||
lcomp *cmp = (lcomp *)compare;
|
||||
unsigned n;
|
||||
|
||||
for( n = *num; n; --n )
|
||||
{
|
||||
if( cmp( key, base ) == 0 )
|
||||
return( base );
|
||||
base = ((char *)base) + width;
|
||||
}
|
||||
memcpy( base, key, width );
|
||||
++*num;
|
||||
return( base );
|
||||
}
|
83
programs/develop/open watcom/trunk/clib/search/qsort.c
Normal file
83
programs/develop/open watcom/trunk/clib/search/qsort.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Open Watcom Project
|
||||
*
|
||||
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original
|
||||
* Code as defined in and that are subject to the Sybase Open Watcom
|
||||
* Public License version 1.0 (the 'License'). You may not use this file
|
||||
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||||
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||||
* provided with the Original Code and Modifications, and is also
|
||||
* available at www.sybase.com/developer/opensource.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||||
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||||
* NON-INFRINGEMENT. Please see the License for the specific language
|
||||
* governing rights and limitations under the License.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
|
||||
* DESCRIBE IT HERE!
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "variety.h"
|
||||
#undef __INLINE_FUNCTIONS__
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "extfunc.h"
|
||||
|
||||
typedef int qcomp( const void *, const void * );
|
||||
#if defined(_M_IX86)
|
||||
#pragma aux (__outside_CLIB) qcomp;
|
||||
#endif
|
||||
|
||||
|
||||
/* Function to find the median value */
|
||||
static char *med3( char *a, char *b, char *c, qcomp cmp )
|
||||
{
|
||||
if( cmp( a, b ) > 0 ) {
|
||||
if( cmp( a, c ) > 0 ) {
|
||||
if( cmp( b, c ) > 0 ) {
|
||||
return( b );
|
||||
} else {
|
||||
return( c );
|
||||
}
|
||||
} else {
|
||||
return( a );
|
||||
}
|
||||
} else {
|
||||
if( cmp( a, c ) >= 0 ) {
|
||||
return( a );
|
||||
} else {
|
||||
if( cmp( b, c ) > 0 ) {
|
||||
return( c );
|
||||
} else {
|
||||
return( b );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef __AXP__
|
||||
|
||||
#else
|
||||
|
||||
#define FUNCTION_LINKAGE _WCRTLINK
|
||||
#define FUNCTION_NAME qsort
|
||||
#define PTRATTR
|
||||
#define MED3 med3
|
||||
#define BYTESWAP byteswap
|
||||
#include "qsortrtn.c"
|
||||
|
||||
#endif
|
118
programs/develop/open watcom/trunk/clib/search/qsort_s.c
Normal file
118
programs/develop/open watcom/trunk/clib/search/qsort_s.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Open Watcom Project
|
||||
*
|
||||
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original
|
||||
* Code as defined in and that are subject to the Sybase Open Watcom
|
||||
* Public License version 1.0 (the 'License'). You may not use this file
|
||||
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||||
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||||
* provided with the Original Code and Modifications, and is also
|
||||
* available at www.sybase.com/developer/opensource.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||||
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||||
* NON-INFRINGEMENT. Please see the License for the specific language
|
||||
* governing rights and limitations under the License.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Description: Implementation of qsort_s() - bounds-checking qsort().
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "variety.h"
|
||||
#include "saferlib.h"
|
||||
#undef __INLINE_FUNCTIONS__
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "extfunc.h"
|
||||
|
||||
typedef int qcomp( const void *, const void *, void * );
|
||||
#if defined(_M_IX86)
|
||||
#pragma aux (__outside_CLIB) qcomp;
|
||||
#endif
|
||||
|
||||
|
||||
/* Function to find the median value */
|
||||
static char *med3( char *a, char *b, char *c, qcomp cmp, void *context )
|
||||
{
|
||||
if( cmp( a, b, context ) > 0 ) {
|
||||
if( cmp( a, c, context ) > 0 ) {
|
||||
if( cmp( b, c, context ) > 0 ) {
|
||||
return( b );
|
||||
} else {
|
||||
return( c );
|
||||
}
|
||||
} else {
|
||||
return( a );
|
||||
}
|
||||
} else {
|
||||
if( cmp( a, c, context ) >= 0 ) {
|
||||
return( a );
|
||||
} else {
|
||||
if( cmp( b, c, context ) > 0 ) {
|
||||
return( c );
|
||||
} else {
|
||||
return( b );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef __AXP__
|
||||
|
||||
#define FUNCTION_LINKAGE static
|
||||
#define FUNCTION_NAME aligned_qsort
|
||||
#define PTRATTR
|
||||
#define MED3 med3
|
||||
#define BYTESWAP aligned_byteswap
|
||||
#include "qsortr_s.c"
|
||||
|
||||
#undef FUNCTION_NAME
|
||||
#undef PTRATTR
|
||||
#undef MED3
|
||||
#undef BYTESWAP
|
||||
#define FUNCTION_NAME unaligned_qsort
|
||||
#define PTRATTR __unaligned
|
||||
#define BYTESWAP unaligned_byteswap
|
||||
#define MED3(a,b,c,f,x) med3( (char*)(a), (char*)(b), (char*)(c), (f), (x) )
|
||||
#include "qsortr_s.c"
|
||||
|
||||
_WCRTLINK errno_t qsort_s( void *in_base, rsize_t n, rsize_t size,
|
||||
int (*compar)( const void *, const void *, void * ),
|
||||
void *context )
|
||||
/*****************************************************************/
|
||||
{
|
||||
/*
|
||||
* If size%4 is 0 and the input base pointer is on a word boundary,
|
||||
* call the aligned version of qsort. Otherwise, call the version
|
||||
* that knows its pointers will be unaligned, so all the fixups can
|
||||
* be done by qsort rather than by expensive OS exceptions.
|
||||
*/
|
||||
if( (size&3) == 0 && (((unsigned)in_base)&3) == 0 ) {
|
||||
return( aligned_qsort( in_base, n, size, compar, context ) );
|
||||
} else {
|
||||
return( unaligned_qsort( (__unaligned void *)in_base, n, size, compar, context ) );
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define FUNCTION_LINKAGE _WCRTLINK
|
||||
#define FUNCTION_NAME qsort_s
|
||||
#define PTRATTR
|
||||
#define MED3 med3
|
||||
#define BYTESWAP byteswap
|
||||
#include "qsortr_s.c"
|
||||
|
||||
#endif
|
360
programs/develop/open watcom/trunk/clib/search/qsortr_s.c
Normal file
360
programs/develop/open watcom/trunk/clib/search/qsortr_s.c
Normal file
@@ -0,0 +1,360 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Open Watcom Project
|
||||
*
|
||||
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original
|
||||
* Code as defined in and that are subject to the Sybase Open Watcom
|
||||
* Public License version 1.0 (the 'License'). You may not use this file
|
||||
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||||
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||||
* provided with the Original Code and Modifications, and is also
|
||||
* available at www.sybase.com/developer/opensource.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||||
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||||
* NON-INFRINGEMENT. Please see the License for the specific language
|
||||
* governing rights and limitations under the License.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Description: Implementation of qsort_s() - bounds-checking qsort().
|
||||
* Included by qsort_s.c.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/* Support OS/2 16-bit protected mode - will never get stack overflow */
|
||||
#define MAXDEPTH (sizeof( long ) * 8)
|
||||
|
||||
#define SHELL 3 /* Shell constant used in shell sort */
|
||||
|
||||
typedef int WORD;
|
||||
#define W sizeof( WORD )
|
||||
|
||||
/*
|
||||
swap() is a macro that chooses between an in_line function call and
|
||||
an exchange macro.
|
||||
*/
|
||||
#define exch( a, b, t) ( t = a, a = b, b = t )
|
||||
#define swap( a, b ) \
|
||||
swaptype != 0 ? BYTESWAP( a, b, size ) : \
|
||||
( void ) exch( *( WORD* )( a ), *( WORD* )( b ), t )
|
||||
|
||||
/*
|
||||
Note: The following assembly was timed against several other methods
|
||||
of doing the same thing. The pragmas here were either fastest on all
|
||||
machines tested, or fastest on most machines tested. (including an 8088,
|
||||
386 16mhz, 386 33mhz, and 486 25mhz).
|
||||
*/
|
||||
|
||||
#if defined( __386__ )
|
||||
/* this is intended for 386 only... */
|
||||
void inline_swap( char *p, char *q, size_t size );
|
||||
#pragma aux inline_swap = \
|
||||
0x06 /* push es */ \
|
||||
0x1e /* push ds */ \
|
||||
0x07 /* pop es */ \
|
||||
0x0f 0xb6 0xd1 /* movzx edx,cl */ \
|
||||
0xc1 0xe9 0x02 /* shr ecx,02H */ \
|
||||
0x74 0x0b /* je L1 */ \
|
||||
0x8b 0x07 /*L2 mov eax,[edi] */ \
|
||||
0x87 0x06 /* xchg eax,[esi] */ \
|
||||
0xab /* stosd */ \
|
||||
0x83 0xc6 0x04 /* add esi,0004H */ \
|
||||
0x49 /* dec ecx */ \
|
||||
0x75 0xf5 /* jne L2 */ \
|
||||
0x80 0xe2 0x03 /*L1 and dl,03H */ \
|
||||
0x74 0x09 /* je L3 */ \
|
||||
0x8a 0x07 /*L4 mov al,[edi] */ \
|
||||
0x86 0x06 /* xchg al,[esi] */ \
|
||||
0xaa /* stosb */ \
|
||||
0x46 /* inc esi */ \
|
||||
0x4a /* dec edx */ \
|
||||
0x75 0xf7 /* jne L4 */ \
|
||||
/*L3 */ \
|
||||
0x07 /* pop es */ \
|
||||
parm caller [esi] [edi] [ecx] \
|
||||
value \
|
||||
modify exact [esi edi ecx eax edx];
|
||||
#pragma aux byteswap parm [esi] [edi] [ecx] \
|
||||
modify exact [esi edi ecx eax edx];
|
||||
static void _WCNEAR byteswap( char *p, char *q, size_t size ) {
|
||||
inline_swap( p, q, size );
|
||||
}
|
||||
|
||||
#elif defined( M_I86 ) && defined( __BIG_DATA__ )
|
||||
void inline_swap( char _WCFAR *p, char _WCFAR *q, size_t size );
|
||||
#pragma aux inline_swap = \
|
||||
0x1e /* push ds */ \
|
||||
0x8e 0xda /* mov ds,dx */ \
|
||||
0xd1 0xe9 /* shr cx,1 */ \
|
||||
0x74 0x0b /* je L1 */ \
|
||||
0x26 0x8b 0x05 /*L2 mov ax,es:[di] */ \
|
||||
0x87 0x04 /* xchg ax,[si] */ \
|
||||
0xab /* stosw */ \
|
||||
0x46 /* inc si */ \
|
||||
0x46 /* inc si */ \
|
||||
0x49 /* dec cx */ \
|
||||
0x75 0xf5 /* jne L2 */ \
|
||||
0x73 0x07 /*L1 jnc L3 */ \
|
||||
0x8a 0x04 /* mov al,[si] */ \
|
||||
0x26 0x86 0x05 /* xchg al,es:[di] */ \
|
||||
0x88 0x04 /* mov [si],al */ \
|
||||
0x1f /*L3 pop ds */ \
|
||||
parm caller [dx si] [es di] [cx] \
|
||||
value \
|
||||
modify exact [si di cx ax];
|
||||
#pragma aux byteswap parm [dx si] [es di] [cx] modify exact [si di cx ax];
|
||||
static void _WCNEAR byteswap( char _WCFAR *p, char _WCFAR *q, size_t size ) {
|
||||
inline_swap( p, q, size );
|
||||
}
|
||||
|
||||
#elif defined( M_I86 ) && defined( __SMALL_DATA__ )
|
||||
/* we'll ask for char __far *q to save us writing code to load es */
|
||||
void inline_swap( char *p, char _WCFAR *q, size_t size );
|
||||
#pragma aux inline_swap = \
|
||||
0xd1 0xe9 /* shr cx,1 */ \
|
||||
0x74 0x0b /* je L1 */ \
|
||||
0x26 0x8b 0x05 /*L2 mov ax,es:[di] */ \
|
||||
0x87 0x04 /* xchg ax,[si] */ \
|
||||
0xab /* stosw */ \
|
||||
0x46 /* inc si */ \
|
||||
0x46 /* inc si */ \
|
||||
0x49 /* dec cx */ \
|
||||
0x75 0xf5 /* jne L2 */ \
|
||||
0x73 0x07 /*L1 jnc L3 */ \
|
||||
0x8a 0x04 /* mov al,[si] */ \
|
||||
0x26 0x86 0x05 /* xchg al,es:[di] */ \
|
||||
0x88 0x04 /* mov [si],al */ \
|
||||
/*L3 */ \
|
||||
parm caller [si] [es di] [cx] \
|
||||
value \
|
||||
modify exact [si di cx ax];
|
||||
#pragma aux byteswap parm [si] [es di] [cx] modify exact [si di cx ax];
|
||||
static void _WCNEAR byteswap( char *p, char _WCFAR *q, size_t size ) {
|
||||
inline_swap( p, q, size );
|
||||
}
|
||||
|
||||
#else
|
||||
/* this is an optimized version of a simple byteswap */
|
||||
#define inline_swap BYTESWAP
|
||||
static void _WCNEAR BYTESWAP( PTRATTR char *p, PTRATTR char *q, size_t size ) {
|
||||
long dword;
|
||||
short word;
|
||||
char byte;
|
||||
|
||||
#if 1 /* this is for 32 bit machines */
|
||||
while( size > 3 ) {
|
||||
dword = *(PTRATTR long *)p;
|
||||
*(PTRATTR long *)p = *(PTRATTR long *)q;
|
||||
*(PTRATTR long *)q = dword;
|
||||
p += 4;
|
||||
q += 4;
|
||||
size -= 4;
|
||||
}
|
||||
if( size > 1 ) {
|
||||
word = *(PTRATTR short *)p;
|
||||
*(PTRATTR short *)p = *(PTRATTR short *)q;
|
||||
*(PTRATTR short *)q = word;
|
||||
p += 2;
|
||||
q += 2;
|
||||
size -= 2;
|
||||
}
|
||||
#else /* this is for 16 bit machines */
|
||||
while( size > 1 ) {
|
||||
word = *(PTRATTR short *)p;
|
||||
*(PTRATTR short *)p = *(PTRATTR short *)q;
|
||||
*(PTRATTR short *)q = word;
|
||||
p += 2;
|
||||
q += 2;
|
||||
size -= 2;
|
||||
}
|
||||
#endif
|
||||
if( size ) {
|
||||
byte = *p;
|
||||
*p = *q;
|
||||
*q = byte;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
FUNCTION_LINKAGE errno_t FUNCTION_NAME( PTRATTR void *in_base,
|
||||
rsize_t n, rsize_t size,
|
||||
int (*compar)( const void *, const void *, void * ),
|
||||
void *context )
|
||||
/*****************************************************************/
|
||||
{
|
||||
PTRATTR char *base = (PTRATTR char*) in_base;
|
||||
PTRATTR char *p1;
|
||||
PTRATTR char *p2;
|
||||
PTRATTR char *pa;
|
||||
PTRATTR char *pb;
|
||||
PTRATTR char *pc;
|
||||
PTRATTR char *pd;
|
||||
PTRATTR char *pn;
|
||||
PTRATTR char *pv;
|
||||
PTRATTR char *mid;
|
||||
WORD v; /* used in pivot initialization */
|
||||
WORD t; /* used in exch() macro */
|
||||
int comparison, swaptype, shell;
|
||||
size_t count, r, s;
|
||||
unsigned sp;
|
||||
auto char *base_stack[MAXDEPTH];
|
||||
unsigned n_stack[MAXDEPTH];
|
||||
qcomp *cmp = (qcomp*)compar;
|
||||
errno_t rc = -1;
|
||||
|
||||
/* runtime-constraints */
|
||||
// n <= RSIZE_MAX
|
||||
// size <= RSIZE_MAX
|
||||
// if n > 0 then in_base, compar not NULL
|
||||
if( __check_constraint_maxsize( n ) &&
|
||||
__check_constraint_maxsize( size ) &&
|
||||
((n == 0) || __check_constraint_nullptr( in_base ) &&
|
||||
__check_constraint_nullptr( compar )) ) {
|
||||
|
||||
if( n == 0 ) { /* empty array - nothing to do */
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
Initialization of the swaptype variable, which determines which
|
||||
type of swapping should be performed when swap() is called.
|
||||
0 for single-word swaps, 1 for general swapping by words, and
|
||||
2 for swapping by bytes. W (it's a macro) = sizeof(WORD).
|
||||
*/
|
||||
swaptype = ( ( base - (char *)0 ) | size ) % W ? 2 : size > W ? 1 : 0;
|
||||
sp = 0;
|
||||
for( ;; ) {
|
||||
while( n > 1 ) {
|
||||
if( n < 16 ) { /* 2-shell sort on smallest arrays */
|
||||
for( shell = (size * SHELL) ;
|
||||
shell > 0 ;
|
||||
shell -= ((SHELL-1) * size) ) {
|
||||
p1 = base + shell;
|
||||
for( ; p1 < base + n * size; p1 += shell ) {
|
||||
for( p2 = p1;
|
||||
p2 > base && cmp( p2 - shell, p2, context ) > 0;
|
||||
p2 -= shell ) {
|
||||
swap( p2, p2 - shell );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else { /* n >= 16 */
|
||||
/* Small array (15 < n < 30), mid element */
|
||||
mid = base + (n >> 1) * size;
|
||||
if( n > 29 ) {
|
||||
p1 = base;
|
||||
p2 = base + ( n - 1 ) * size;
|
||||
if( n > 42 ) { /* Big array, pseudomedian of 9 */
|
||||
s = (n >> 3) * size;
|
||||
p1 = MED3( p1, p1 + s, p1 + (s << 1), cmp, context );
|
||||
mid = MED3( mid - s, mid, mid + s, cmp, context );
|
||||
p2 = MED3( p2 - (s << 1), p2 - s, p2, cmp, context );
|
||||
}
|
||||
/* Mid-size (29 < n < 43), med of 3 */
|
||||
mid = MED3( p1, mid, p2, cmp, context );
|
||||
}
|
||||
/*
|
||||
The following sets up the pivot (pv) for partitioning.
|
||||
It's better to store the pivot value out of line
|
||||
instead of swapping it to base. However, it's
|
||||
inconvenient in C unless the element size is fixed.
|
||||
So, only the important special case of word-size
|
||||
objects has utilized it.
|
||||
*/
|
||||
if( swaptype != 0 ) { /* Not word-size objects */
|
||||
pv = base;
|
||||
swap( pv, mid );
|
||||
} else { /* Storing the pivot out of line (at v) */
|
||||
pv = (char *)&v;
|
||||
v = *(WORD *)mid;
|
||||
}
|
||||
|
||||
pa = pb = base;
|
||||
pc = pd = base + ( n - 1 ) * size;
|
||||
count = n;
|
||||
/*
|
||||
count keeps track of how many entries we have
|
||||
examined. Once we have looked at all the entries
|
||||
then we know that the partitioning is complete.
|
||||
We use count to terminate the looping, rather than
|
||||
a pointer comparison, to handle 16bit pointer
|
||||
limitations that may lead pb or pc to wrap.
|
||||
i.e. pc = 0x0000;
|
||||
pc -= 0x0004;
|
||||
pc == 0xfffc;
|
||||
pc is no longer less that 0x0000;
|
||||
*/
|
||||
for( ;; ) {
|
||||
while( count && (comparison = cmp(pb, pv, context )) <= 0 ) {
|
||||
if( comparison == 0 ) {
|
||||
swap( pa, pb );
|
||||
pa += size;
|
||||
}
|
||||
pb += size;
|
||||
count--;
|
||||
}
|
||||
while( count && (comparison = cmp(pc, pv, context )) >= 0 ) {
|
||||
if( comparison == 0 ) {
|
||||
swap( pc, pd );
|
||||
pd -= size;
|
||||
}
|
||||
pc -= size;
|
||||
count--;
|
||||
}
|
||||
if( !count ) break;
|
||||
swap( pb, pc );
|
||||
pb += size;
|
||||
count--;
|
||||
if( !count ) break;
|
||||
pc -= size;
|
||||
count--;
|
||||
}
|
||||
pn = base + n * size;
|
||||
s = min( pa - base, pb - pa );
|
||||
if( s > 0 ) {
|
||||
inline_swap( base, pb - s, s );
|
||||
}
|
||||
s = min( pd - pc, pn - pd - size);
|
||||
if( s > 0 ) {
|
||||
inline_swap( pb, pn - s, s );
|
||||
}
|
||||
/* Now, base to (pb-pa) needs to be sorted */
|
||||
/* Also, pn-(pd-pc) needs to be sorted */
|
||||
/* The middle 'chunk' contains all elements=pivot value */
|
||||
r = pb - pa;
|
||||
s = pd - pc;
|
||||
if( s >= r ) { /* Stack up the larger chunk */
|
||||
base_stack[sp] = pn - s; /* Stack up base */
|
||||
n_stack[sp] = s / size; /* Stack up n */
|
||||
n = r / size; /* Set up n for next 'call' */
|
||||
/* next base is still base */
|
||||
} else {
|
||||
if( r <= size ) break;
|
||||
base_stack[sp] = base; /* Stack up base */
|
||||
n_stack[sp] = r / size; /* Stack up n */
|
||||
base = pn - s; /* Set up base and n for */
|
||||
n = s / size; /* next 'call' */
|
||||
}
|
||||
++sp;
|
||||
}
|
||||
}
|
||||
if( sp == 0 ) break;
|
||||
--sp;
|
||||
base = base_stack[sp];
|
||||
n = n_stack[sp];
|
||||
}
|
||||
rc = 0;
|
||||
}
|
||||
return( rc );
|
||||
}
|
349
programs/develop/open watcom/trunk/clib/search/qsortrtn.c
Normal file
349
programs/develop/open watcom/trunk/clib/search/qsortrtn.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Open Watcom Project
|
||||
*
|
||||
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original
|
||||
* Code as defined in and that are subject to the Sybase Open Watcom
|
||||
* Public License version 1.0 (the 'License'). You may not use this file
|
||||
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||||
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||||
* provided with the Original Code and Modifications, and is also
|
||||
* available at www.sybase.com/developer/opensource.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||||
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||||
* NON-INFRINGEMENT. Please see the License for the specific language
|
||||
* governing rights and limitations under the License.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
|
||||
* DESCRIBE IT HERE!
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* This file is #included by qsort.c.
|
||||
*/
|
||||
|
||||
|
||||
/* Support OS/2 16-bit protected mode - will never get stack overflow */
|
||||
#define MAXDEPTH (sizeof(long) * 8)
|
||||
|
||||
#define SHELL 3 /* Shell constant used in shell sort */
|
||||
|
||||
typedef int WORD;
|
||||
#define W sizeof( WORD )
|
||||
|
||||
/*
|
||||
swap() is a macro that chooses between an in_line function call and
|
||||
an exchange macro.
|
||||
*/
|
||||
#define exch( a, b, t) ( t = a, a = b, b = t )
|
||||
#define swap( a, b ) \
|
||||
swaptype != 0 ? BYTESWAP( a, b, size ) : \
|
||||
( void ) exch( *( WORD* )( a ), *( WORD* )( b ), t )
|
||||
|
||||
/*
|
||||
Note: The following assembly was timed against several other methods
|
||||
of doing the same thing. The pragmas here were either fastest on all
|
||||
machines tested, or fastest on most machines tested. (including an 8088,
|
||||
386 16mhz, 386 33mhz, and 486 25mhz).
|
||||
*/
|
||||
|
||||
#if defined( __386__ )
|
||||
/* this is intended for 386 only... */
|
||||
void inline_swap( char *p, char *q, size_t size );
|
||||
#pragma aux inline_swap = \
|
||||
0x06 /* push es */ \
|
||||
0x1e /* push ds */ \
|
||||
0x07 /* pop es */ \
|
||||
0x0f 0xb6 0xd1 /* movzx edx,cl */ \
|
||||
0xc1 0xe9 0x02 /* shr ecx,02H */ \
|
||||
0x74 0x0b /* je L1 */ \
|
||||
0x8b 0x07 /*L2 mov eax,[edi] */ \
|
||||
0x87 0x06 /* xchg eax,[esi] */ \
|
||||
0xab /* stosd */ \
|
||||
0x83 0xc6 0x04 /* add esi,0004H */ \
|
||||
0x49 /* dec ecx */ \
|
||||
0x75 0xf5 /* jne L2 */ \
|
||||
0x80 0xe2 0x03 /*L1 and dl,03H */ \
|
||||
0x74 0x09 /* je L3 */ \
|
||||
0x8a 0x07 /*L4 mov al,[edi] */ \
|
||||
0x86 0x06 /* xchg al,[esi] */ \
|
||||
0xaa /* stosb */ \
|
||||
0x46 /* inc esi */ \
|
||||
0x4a /* dec edx */ \
|
||||
0x75 0xf7 /* jne L4 */ \
|
||||
/*L3 */ \
|
||||
0x07 /* pop es */ \
|
||||
parm caller [esi] [edi] [ecx] \
|
||||
value \
|
||||
modify exact [esi edi ecx eax edx];
|
||||
#pragma aux byteswap parm [esi] [edi] [ecx] \
|
||||
modify exact [esi edi ecx eax edx];
|
||||
static void _WCNEAR byteswap( char *p, char *q, size_t size ) {
|
||||
inline_swap( p, q, size );
|
||||
}
|
||||
|
||||
#elif defined( M_I86 ) && defined( __BIG_DATA__ )
|
||||
void inline_swap( char _WCFAR *p, char _WCFAR *q, size_t size );
|
||||
#pragma aux inline_swap = \
|
||||
0x1e /* push ds */ \
|
||||
0x8e 0xda /* mov ds,dx */ \
|
||||
0xd1 0xe9 /* shr cx,1 */ \
|
||||
0x74 0x0b /* je L1 */ \
|
||||
0x26 0x8b 0x05 /*L2 mov ax,es:[di] */ \
|
||||
0x87 0x04 /* xchg ax,[si] */ \
|
||||
0xab /* stosw */ \
|
||||
0x46 /* inc si */ \
|
||||
0x46 /* inc si */ \
|
||||
0x49 /* dec cx */ \
|
||||
0x75 0xf5 /* jne L2 */ \
|
||||
0x73 0x07 /*L1 jnc L3 */ \
|
||||
0x8a 0x04 /* mov al,[si] */ \
|
||||
0x26 0x86 0x05 /* xchg al,es:[di] */ \
|
||||
0x88 0x04 /* mov [si],al */ \
|
||||
0x1f /*L3 pop ds */ \
|
||||
parm caller [dx si] [es di] [cx] \
|
||||
value \
|
||||
modify exact [si di cx ax];
|
||||
#pragma aux byteswap parm [dx si] [es di] [cx] modify exact [si di cx ax];
|
||||
static void _WCNEAR byteswap( char _WCFAR *p, char _WCFAR *q, size_t size ) {
|
||||
inline_swap( p, q, size );
|
||||
}
|
||||
|
||||
#elif defined( M_I86 ) && defined( __SMALL_DATA__ )
|
||||
/* we'll ask for char __far *q to save us writing code to load es */
|
||||
void inline_swap( char *p, char _WCFAR *q, size_t size );
|
||||
#pragma aux inline_swap = \
|
||||
0xd1 0xe9 /* shr cx,1 */ \
|
||||
0x74 0x0b /* je L1 */ \
|
||||
0x26 0x8b 0x05 /*L2 mov ax,es:[di] */ \
|
||||
0x87 0x04 /* xchg ax,[si] */ \
|
||||
0xab /* stosw */ \
|
||||
0x46 /* inc si */ \
|
||||
0x46 /* inc si */ \
|
||||
0x49 /* dec cx */ \
|
||||
0x75 0xf5 /* jne L2 */ \
|
||||
0x73 0x07 /*L1 jnc L3 */ \
|
||||
0x8a 0x04 /* mov al,[si] */ \
|
||||
0x26 0x86 0x05 /* xchg al,es:[di] */ \
|
||||
0x88 0x04 /* mov [si],al */ \
|
||||
/*L3 */ \
|
||||
parm caller [si] [es di] [cx] \
|
||||
value \
|
||||
modify exact [si di cx ax];
|
||||
#pragma aux byteswap parm [si] [es di] [cx] modify exact [si di cx ax];
|
||||
static void _WCNEAR byteswap( char *p, char _WCFAR *q, size_t size ) {
|
||||
inline_swap( p, q, size );
|
||||
}
|
||||
|
||||
#else
|
||||
/* this is an optimized version of a simple byteswap */
|
||||
#define inline_swap BYTESWAP
|
||||
static void _WCNEAR BYTESWAP( PTRATTR char *p, PTRATTR char *q, size_t size ) {
|
||||
long dword;
|
||||
short word;
|
||||
char byte;
|
||||
|
||||
#if 1 /* this is for 32 bit machines */
|
||||
while( size > 3 ) {
|
||||
dword = *(PTRATTR long *)p;
|
||||
*(PTRATTR long *)p = *(PTRATTR long *)q;
|
||||
*(PTRATTR long *)q = dword;
|
||||
p += 4;
|
||||
q += 4;
|
||||
size -= 4;
|
||||
}
|
||||
if( size > 1 ) {
|
||||
word = *(PTRATTR short *)p;
|
||||
*(PTRATTR short *)p = *(PTRATTR short *)q;
|
||||
*(PTRATTR short *)q = word;
|
||||
p += 2;
|
||||
q += 2;
|
||||
size -= 2;
|
||||
}
|
||||
#else /* this is for 16 bit machines */
|
||||
while( size > 1 ) {
|
||||
word = *(PTRATTR short *)p;
|
||||
*(PTRATTR short *)p = *(PTRATTR short *)q;
|
||||
*(PTRATTR short *)q = word;
|
||||
p += 2;
|
||||
q += 2;
|
||||
size -= 2;
|
||||
}
|
||||
#endif
|
||||
if( size ) {
|
||||
byte = *p;
|
||||
*p = *q;
|
||||
*q = byte;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
FUNCTION_LINKAGE void FUNCTION_NAME(
|
||||
PTRATTR void *in_base, size_t n,
|
||||
size_t size,
|
||||
int (*compar)(const void *, const void *)
|
||||
)
|
||||
/**********************************************************************/
|
||||
{
|
||||
PTRATTR char * base = (PTRATTR char*) in_base;
|
||||
PTRATTR char * p1;
|
||||
PTRATTR char * p2;
|
||||
PTRATTR char * pa;
|
||||
PTRATTR char * pb;
|
||||
PTRATTR char * pc;
|
||||
PTRATTR char * pd;
|
||||
PTRATTR char * pn;
|
||||
PTRATTR char * pv;
|
||||
PTRATTR char * mid;
|
||||
WORD v; /* used in pivot initialization */
|
||||
WORD t; /* used in exch() macro */
|
||||
int comparison, swaptype, shell;
|
||||
size_t count, r, s;
|
||||
unsigned int sp;
|
||||
auto char * base_stack[MAXDEPTH];
|
||||
auto unsigned int n_stack[MAXDEPTH];
|
||||
qcomp * cmp = (qcomp*) compar;
|
||||
|
||||
/*
|
||||
Initialization of the swaptype variable, which determines which
|
||||
type of swapping should be performed when swap() is called.
|
||||
0 for single-word swaps, 1 for general swapping by words, and
|
||||
2 for swapping by bytes. W (it's a macro) = sizeof(WORD).
|
||||
*/
|
||||
swaptype = ( ( base - (char *)0 ) | size ) % W ? 2 : size > W ? 1 : 0;
|
||||
sp = 0;
|
||||
for(;;) {
|
||||
while( n > 1 ) {
|
||||
if( n < 16 ) { /* 2-shell sort on smallest arrays */
|
||||
for( shell = (size * SHELL) ;
|
||||
shell > 0 ;
|
||||
shell -= ((SHELL-1) * size) ) {
|
||||
p1 = base + shell;
|
||||
for( ; p1 < base + n * size; p1 += shell ) {
|
||||
for( p2 = p1;
|
||||
p2 > base && cmp( p2 - shell, p2 ) > 0;
|
||||
p2 -= shell ) {
|
||||
swap( p2, p2 - shell );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else { /* n >= 16 */
|
||||
/* Small array (15 < n < 30), mid element */
|
||||
mid = base + (n >> 1) * size;
|
||||
if( n > 29 ) {
|
||||
p1 = base;
|
||||
p2 = base + ( n - 1 ) * size;
|
||||
if( n > 42 ) { /* Big array, pseudomedian of 9 */
|
||||
s = (n >> 3) * size;
|
||||
p1 = MED3( p1, p1 + s, p1 + (s << 1), cmp );
|
||||
mid = MED3( mid - s, mid, mid + s, cmp );
|
||||
p2 = MED3( p2 - (s << 1), p2 - s, p2, cmp );
|
||||
}
|
||||
/* Mid-size (29 < n < 43), med of 3 */
|
||||
mid = MED3( p1, mid, p2, cmp );
|
||||
}
|
||||
/*
|
||||
The following sets up the pivot (pv) for partitioning.
|
||||
It's better to store the pivot value out of line
|
||||
instead of swapping it to base. However, it's
|
||||
inconvenient in C unless the element size is fixed.
|
||||
So, only the important special case of word-size
|
||||
objects has utilized it.
|
||||
*/
|
||||
if( swaptype != 0 ) { /* Not word-size objects */
|
||||
pv = base;
|
||||
swap( pv, mid );
|
||||
} else { /* Storing the pivot out of line (at v) */
|
||||
pv = ( char* )&v;
|
||||
v = *( WORD* )mid;
|
||||
}
|
||||
|
||||
pa = pb = base;
|
||||
pc = pd = base + ( n - 1 ) * size;
|
||||
count = n;
|
||||
/*
|
||||
count keeps track of how many entries we have
|
||||
examined. Once we have looked at all the entries
|
||||
then we know that the partitioning is complete.
|
||||
We use count to terminate the looping, rather than
|
||||
a pointer comparison, to handle 16bit pointer
|
||||
limitations that may lead pb or pc to wrap.
|
||||
i.e. pc = 0x0000;
|
||||
pc -= 0x0004;
|
||||
pc == 0xfffc;
|
||||
pc is no longer less that 0x0000;
|
||||
*/
|
||||
for(;;) {
|
||||
while(count && (comparison = cmp(pb, pv)) <= 0) {
|
||||
if( comparison == 0 ) {
|
||||
swap( pa, pb );
|
||||
pa += size;
|
||||
}
|
||||
pb += size;
|
||||
count--;
|
||||
}
|
||||
while(count && (comparison = cmp(pc, pv)) >= 0) {
|
||||
if( comparison == 0 ) {
|
||||
swap( pc, pd );
|
||||
pd -= size;
|
||||
}
|
||||
pc -= size;
|
||||
count--;
|
||||
}
|
||||
if( !count ) break;
|
||||
swap( pb, pc );
|
||||
pb += size;
|
||||
count--;
|
||||
if( !count ) break;
|
||||
pc -= size;
|
||||
count--;
|
||||
}
|
||||
pn = base + n * size;
|
||||
s = min( pa - base, pb - pa );
|
||||
if( s > 0 ) {
|
||||
inline_swap( base, pb - s, s );
|
||||
}
|
||||
s = min( pd - pc, pn - pd - size);
|
||||
if( s > 0 ) {
|
||||
inline_swap( pb, pn - s, s );
|
||||
}
|
||||
/* Now, base to (pb-pa) needs to be sorted */
|
||||
/* Also, pn-(pd-pc) needs to be sorted */
|
||||
/* The middle 'chunk' contains all elements=pivot value*/
|
||||
r = pb - pa;
|
||||
s = pd - pc;
|
||||
if( s >= r ) { /* Stack up the larger chunk */
|
||||
base_stack[sp] = pn - s;/* Stack up base */
|
||||
n_stack[sp] = s / size; /* Stack up n */
|
||||
n = r / size; /* Set up n for next 'call'*/
|
||||
/* next base is still base */
|
||||
} else {
|
||||
if( r <= size ) break;
|
||||
base_stack[sp] = base; /* Stack up base */
|
||||
n_stack[sp] = r / size; /* Stack up n */
|
||||
base = pn - s; /* Set up base and n for */
|
||||
n = s / size; /* next 'call' */
|
||||
}
|
||||
++sp;
|
||||
}
|
||||
}
|
||||
if( sp == 0 ) break;
|
||||
--sp;
|
||||
base = base_stack[sp];
|
||||
n = n_stack[sp];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user