home *** CD-ROM | disk | FTP | other *** search
- /* $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;
- }
-
-
-
-
-