home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR2
/
CBUFF09.ZIP
/
SRC.ZIP
/
SORT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-16
|
8KB
|
357 lines
/* $Id$
*
* File sort.c
* Part of ChessBase utilities file format (CBUFF)
* Author Anjo Anjewierden, anjo@swi.psy.uva.nl
* Urban Koistinen, md85-epi@nada.kth.se
* Purpose Sorting utility
* Works with GNU CC 2.4.5
*
* Notice Copyright (c) 1993 Anjo Anjewierden
*
* History 10/07/93 (Created)
* 03/11/93 (Last modified)
*/
/*------------------------------------------------------------
* Directives
*------------------------------------------------------------*/
#include "cbuff.h"
char * UTILITY_NAME = "Sort utility";
char * UTILITY_VERSION = "1.1.0";
void helpUtility(FILE *fd);
void sortUtility(Option);
/*------------------------------------------------------------
* Definitions
*------------------------------------------------------------*/
static CBase SortBase;
static int compareSortData(const void *, const void *);
static char * prepare_key(char *, char *, char *, short, char *, long);
static int addchar(unsigned char *, unsigned char);
static int addstring(unsigned char *, unsigned char *, int);
static int addshort(unsigned char *, short);
static void storelong(unsigned char *, unsigned long);
#define SORT_WHITE 1
#define SORT_BLACK 2
#define SORT_SOURCE 3
#define SORT_ECO 4
#define SORT_YEAR 5
struct sort_option
{ int option;
int count;
} SortOptions[10];
typedef unsigned char * SortData;
int NoSortOptions = 0;
/*------------------------------------------------------------
* Sort utility
*------------------------------------------------------------*/
void
sortUtility(Option opt)
{ CBase cb = opt->database;
long n = getNoGamesCBase(cb);
SortData *sd;
long i;
Game g = newGame();
long inc, count;
long k; /* Games to be sorted */
printMemoryAvailable(stderr);
reportCBase(cb, stderr);
if (opt->dump == NULL)
{ fprintf(stderr, "No output database specified (-dump/-append option)\n");
exit(1);
}
if (NoSortOptions == 0)
{ fprintf(stderr, "No sort options specified; cannot sort\n");
exit(1);
}
sd = alloc(sizeof(SortData) * n);
if (sd == NULL)
{ fprintf(stderr, "Not enough memory for sort\n");
exit(1);
}
inc = (n < 50L ? 1 : n / 50);
printMemoryAvailable(stderr);
fprintf(stderr, "Reading games from database %s\n", cb->name);
for (i=1, count=0, k=0; i<=n; i++, count++)
{ if (inc == count)
{ fprintf(stderr, ".");
count = 0;
}
environmentError(cb, g, i);
initialiseGame(g, i, cb);
if (foundError())
{ reportError(stderr);
continue;
}
{ char *black = getBlackGame(g);
char *white = getWhiteGame(g);
char *source = getSourceGame(g);
char *eco = getEcoGame(g);
short year = getYearGame(g);
unsigned long index = getIndexGameCBase(cb, i);
if (foundError())
{ reportError(stderr);
continue;
}
if (white == NULL) /* So games are at least partially sort correctly. */
white = getPlayersGame(g);
sd[k++] = prepare_key(black, white, source, year, eco, index);
}
}
fprintf(stderr, " Done!\n");
printMemoryAvailable(stderr);
SortBase = cb;
fprintf(stderr, "Sorting games ");
qsort(sd, (size_t) k, sizeof(SortData), compareSortData);
fprintf(stderr, " Done!\n");
for (i=0; i<k; i++)
{ unsigned long val;
val = (unsigned char) sd[i][-4];
val <<= 8; val |= (unsigned char) sd[i][-3];
val <<= 8; val |= (unsigned char) sd[i][-2];
val <<= 8; val |= (unsigned char) sd[i][-1];
cb->index[i] = val;
}
exportManyCBase(opt->dump, cb, 1, k);
}
/*------------------------------------------------------------
* Main
*------------------------------------------------------------*/
int
main(int argc, char *argv[])
{ int i;
Option options = newOption();
for (i=1; i<argc; i++)
{
if (strhead(argv[i], "-white")) /* -white */
{ i++;
SortOptions[NoSortOptions].option = SORT_WHITE;
SortOptions[NoSortOptions++].count = intArgument(argv[i],"-white",argc,i);
continue;
}
if (strhead(argv[i], "-black")) /* -black */
{ i++;
SortOptions[NoSortOptions].option = SORT_BLACK;
SortOptions[NoSortOptions++].count = intArgument(argv[i],"-black",argc,i);
continue;
}
if (strhead(argv[i], "-eco")) /* -eco */
{ SortOptions[NoSortOptions++].option = SORT_ECO;
continue;
}
if (strhead(argv[i], "-source")) /* -source */
{ i++;
SortOptions[NoSortOptions].option = SORT_SOURCE;
SortOptions[NoSortOptions++].count = intArgument(argv[i],"-source",argc,i);
continue;
}
if (strhead(argv[i], "-year")) /* -year */
{ SortOptions[NoSortOptions++].option = SORT_YEAR;
continue;
}
if (strhead(argv[i], "-"))
{ int n;
n = genericOption(options, argv, argc, i);
if (n == 0)
{ fprintf(stderr, "Fatal: Unknown command %s\n", argv[i]);
fprintf(stderr, "Do ``%s -help'' or see the documentation\n", argv[0]);
exit(1);
}
i = n;
continue;
}
setCurrentCBase(argv[i], "-database", argc, i);
options->database = CurrentBase;
sortUtility(options);
freeCBase(options->database);
options->database = (CBase) NULL;
}
if (options->database)
{ sortUtility(options);
freeCBase(options->database);
}
exit(0);
}
/*------------------------------------------------------------
* Help
*------------------------------------------------------------*/
void
helpUtility(FILE *fd)
{ helpCBUFF(fd);
fprintf(fd, "%s options:\n", UTILITY_NAME);
fprintf(fd, "-black n Use n characters of Black (0: entire name)\n");
fprintf(fd, "-eco Compare by ascending ECO\n");
fprintf(fd, "-source n Use n characters of source (0: entire source)\n");
fprintf(fd, "-white n Use n characters of White (0: entire name)\n");
fprintf(fd, "-year Compare by ascending year\n");
}
/*------------------------------------------------------------
* Implementation
*------------------------------------------------------------*/
static int
addchar(unsigned char *buf, unsigned char c)
{ if (c < 3)
{ if (c==0)
{ buf[0] = 1;
return 1;
} else
{ buf[0] = 2;
buf[1] = c;
return 2;
}
}
buf[0] = c;
return 1;
}
static int
addstring(unsigned char *buf, unsigned char *s, int count)
{ int i = 0;
if (s)
{ for (;*s && count--; s++)
i += addchar(&buf[i], *s);
i += addchar(&buf[i], *s);
} else
i += addchar(&buf[i], '\0');
return i;
}
static int
addshort(unsigned char *buf, short n)
{ int i;
i = addchar(buf, ((n>>8)+0x80)&0xff);
i += addchar(&buf[i], n&0xff);
return i;
}
static void
storelong(unsigned char *buf, unsigned long n)
{ buf[0] = (unsigned char) (n>>24);
buf[1] = (unsigned char) (n>>16);
buf[2] = (unsigned char) (n>>8);
buf[3] = (unsigned char) n;
}
static int
compareSortData(const void *a, const void *b)
{ char *s1 = *((char **) a);
char *s2 = *((char **) b);
return strcmp(s1, s2);
}
static char *
prepare_key(char *black, char *white, char *source, short year, char *eco, long index)
{ unsigned char buf[500];
int i, j;
unsigned char *s;
i = 0;
for (j=0;j<NoSortOptions;j++)
{ int option = SortOptions[j].option;
int count = SortOptions[j].count;
switch (option)
{ case SORT_WHITE:
i += addstring(&buf[i], white, count);
break;
case SORT_BLACK:
i += addstring(&buf[i], black, count);
break;
case SORT_SOURCE:
i += addstring(&buf[i], source, count);
break;
case SORT_ECO:
i += addstring(&buf[i], eco, 7);
break;
case SORT_YEAR:
i += addshort(&buf[i], year);
break;
default:
fprintf(stderr, "Internal error: Unknown sort option (%d)\n", option);
exit(1);
}
}
buf[i] = '\0';
if (i && (buf[i-1]==1))
buf[--i] = '\0';
if ((s = alloc(i+5)) == NULL)
{ fprintf(stderr, "Not enough memory for sort key\n");
exit(1);
}
storelong(s, index);
s += 4;
strcpy(s, buf);
return s;
}