/*
** On 6 September 2008, I posted pqsort.
**
**
http://groups.google.com/group/comp.lang.c/msg/6a73e359f4814457
**
** This is a version of listgen.c with a new QSORT based on pqsort.
** It's an introspective quicksort.
** If you like, I can toss in a PRNG for the pivot selection.
** Try it.
*/
/* BEGIN listgen.c */
/*
* Value types generic list routines sample implementation
* ----------------------------------- ------------------
* Thisroutines handle the List container class. This is a very general
* implementation and efficiency considerations aren't yet primordial.
Lists
* can have elements of any size. This implement single linked Lists.
The
* design goals here are just correctness and showing how the
implementation
* of the proposed interface COULD be done.
*
----------------------------------------------------------------------
*/
#include "listgen.h"
#include "ccl_internal.h"
#include <assert.h>
/* Forward declarations */
static LIST_TYPE *SetVTable(LIST_TYPE *result);
static LIST_TYPE * Create(size_t elementsize);
static LIST_TYPE *CreateWithAllocator(size_t elementsize, const
ContainerAllocator * allocator);
#define CONTAINER_LIST_SMALL 2
#define CHUNK_SIZE 1000
static int DefaultListCompareFunction(const void * left, const void *
right, CompareInfo * ExtraArgs)
{
size_t siz = ((LIST_TYPE *)
ExtraArgs->ContainerLeft)->ElementSize;
return memcmp(left, right, siz);
}
/*------------------------------------------------------------------------
Procedure: Contains ID:1
Purpose: Determines if the given data is in the container
Input: The list and the data to be searched
Output: Returns 1 (true) if the data is in there, false
otherwise
Errors: The same as the function IndexOf
------------------------------------------------------------------------*/
static int Contains(const LIST_TYPE * l, const DATA_TYPE data)
{
size_t idx;
return (iList.IndexOf((List *)l, &data, NULL, &idx) < 0) ? 0 : 1;
}
static int Add(LIST_TYPE * l, const DATA_TYPE elem)
{
return iList.Add((List *)l,&elem);
}
/*------------------------------------------------------------------------
Procedure: GetElement ID:1
Purpose: Returns the data associated with a given position
Input: The list and the position
Output: A pointer to the data
Errors: NULL if error in the positgion index
------------------------------------------------------------------------*/
static DATA_TYPE GetElement(const LIST_TYPE * l, size_t position)
{
DATA_TYPE *pdata = iList.GetElement((List *)l,position);
if (pdata == NULL) return ERROR_RETURN;
return *pdata;
}
static DATA_TYPE Back(const LIST_TYPE * l)
{
DATA_TYPE *p = (DATA_TYPE *)iList.Back((List *)l);
if (p == NULL) return ERROR_RETURN;
return *p;
}
static DATA_TYPE Front(const LIST_TYPE * l)
{
DATA_TYPE *p = (DATA_TYPE *)iList.Front((List *)l);
if (p == NULL) return ERROR_RETURN;
return *p;
}
static int CopyElement(const LIST_TYPE * l, size_t position, DATA_TYPE
*outBuffer)
{
return iList.CopyElement((List *)l,position,outBuffer);
}
static int ReplaceAt(LIST_TYPE * l, size_t position, const DATA_TYPE
data)
{
return iList.ReplaceAt((List *)l,position,&data);;
}
static int PushFront(LIST_TYPE * l, const DATA_TYPE pdata)
{
return iList.PushFront((List *)l,&pdata);
}
static int PopFront(LIST_TYPE * l, DATA_TYPE *result)
{
return iList.PushFront((List *)l,result);
}
static int InsertAt(LIST_TYPE * l, size_t pos, const DATA_TYPE pdata)
{
return iList.InsertAt((List *)l,pos,&pdata);
}
static int Erase(LIST_TYPE * l, const DATA_TYPE elem)
{
return iList.Erase((List *)l, &elem);
}
static int EraseAll(LIST_TYPE * l, const DATA_TYPE elem)
{
return iList.EraseAll((List *)l, &elem);
}
static int IndexOf(const LIST_TYPE * l, const DATA_TYPE ElementToFind,
void *ExtraArgs, size_t * result)
{
return iList.IndexOf((List *)l, &ElementToFind, ExtraArgs, result);
}
static size_t Sizeof(const LIST_TYPE * l)
{
if (l == NULL) {
return sizeof(List);
}
return sizeof(LIST_TYPE) + l->ElementSize * l->count + l->count *
offsetof(LIST_ELEMENT,Data);
}
static size_t SizeofIterator(const LIST_TYPE * l)
{
return sizeof(struct ITERATOR(DATA_TYPE));
}
static LIST_TYPE *Load(FILE * stream, ReadFunction loadFn, void *arg)
{
LIST_TYPE *result = (LIST_TYPE *)iList.Load(stream,loadFn,arg);
return SetVTable(result);
}
/*
*
---------------------------------------------------------------------------
*
* Iterators
*
*
---------------------------------------------------------------------------
*/
static int ReplaceWithIterator(Iterator * it, DATA_TYPE data, int
direction)
{
struct ITERATOR(DATA_TYPE) *iter = (struct ITERATOR(DATA_TYPE) *)it;
return iter->ListReplace(it,&data,direction);
}
static Iterator *SetupIteratorVTable(struct ITERATOR(DATA_TYPE) *result)
{
if (result == NULL) return NULL;
result->ListReplace = result->it.Replace;
result->it.Replace = (int (*)(Iterator * , void * , int
))ReplaceWithIterator;
return &result->it;
}
static Iterator *NewIterator(LIST_TYPE * L)
{
return SetupIteratorVTable((struct ITERATOR(DATA_TYPE)
*)iList.NewIterator((List *)L));
}
static int InitIterator(LIST_TYPE * L, void *r)
{
iList.InitIterator((List *)L,r);
SetupIteratorVTable(r);
return 1;
}
static size_t GetElementSize(const LIST_TYPE * l)
{
return sizeof(DATA_TYPE);
}
static int Finalize(LIST_TYPE *l)
{
iList.Finalize((List *)l);
return 1;
}
static LIST_TYPE *Copy(const LIST_TYPE * l)
{
LIST_TYPE *result = (LIST_TYPE *)iList.Copy((List *)l);
return SetVTable(result);
}
static LIST_TYPE *SelectCopy(const LIST_TYPE *l,const Mask *m)
{
LIST_TYPE *result = (LIST_TYPE *)iList.SelectCopy((const List
*)l,m);
return SetVTable(result);
}
/*---------------------------------------------------------------------------*/
/* qsort() - perform a quicksort on an
array */
/*---------------------------------------------------------------------------*/
#ifndef COMPARE_EXPRESSION
#error foo
#define COMPARE_EXPRESSION(l,lo) comp(l, lo)
//COMPAR(A, B) (B > A ? -1 : B != A)
#endif
#define E_TYPE LIST_ELEMENT *e_type
#define GT(A, B) (COMPARE_EXPRESSION((A), (B)) > 0)
#define MOV(A, B) ((void)(*(A) = *(B)))
#define SMALL_PARTITION 8
#define SWAP(A, B, T) \
(MOV((T), (A)), MOV((A), (B)), MOV((B), (T)))
#define SORT_3(A, B, C, T) \
if (GT((A), (B))) { \
MOV((T), (A)); \
if (GT((C), (B))) { \
MOV((A), (B)); \
if (GT((T), (C))) { \
MOV((B), (C)); \
MOV((C), (T)); \
} else { \
MOV((B), (T)); \
} \
} else { \
MOV((A), (C)); \
MOV((C), (T)); \
} \
} else { \
if (GT((B), (C))) { \
MOV((T), (B)); \
if (GT((A), (C))) { \
MOV((B), (A)); \
MOV((A), (C)); \
} else { \
MOV((B), (C)); \
} \
MOV((C), (T)); \
} \
}
#define SIFTDOWNM(P) \
{ \
parent = (P); \
child = parent * 2; \
MOV(&temp, array + parent); \
while (nmemb - parent > parent) { \
if (GT(array + child + 1, array + child)) { \
++child; \
} \
if (GT(array + child, &temp)) { \
MOV(array + parent, array + child); \
parent = child; \
child *= 2; \
} else { \
break; \
} \
} \
if (nmemb == child && GT(array + child, &temp)) { \
MOV(array + parent, array + child); \
parent = child; \
} \
MOV(array + parent, &temp); \
}
typedef E_TYPE;
static void sisort(e_type *array, size_t nmemb)
{
e_type *base, *low, *high, temp;
if (nmemb-- > 1) {
base = array;
do {
low = array++;
if (GT(low, array)) {
high = array;
MOV(&temp, high);
do {
MOV(high, low);
if (--high == base) {
break;
}
--low;
} while (GT(low, &temp));
MOV(high, &temp);
}
} while (--nmemb != 0);
}