chiark / gitweb /
Quick lick of paint before we really get started.
[anag] / mono.c
1 /* -*-c-*-
2  *
3  * Monoalphabetic matcher
4  *
5  * (c) 2003 Mark Wooding
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Anag: a simple wordgame helper.
11  *
12  * Anag is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Anag is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Anag; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /*----- Header files ------------------------------------------------------*/
28
29 #include "anag.h"
30
31 /*----- Data structures ---------------------------------------------------*/
32
33 typedef struct node_mono {
34   node n;
35   unsigned len;
36   unsigned char *p;
37 } node_mono;
38
39 /*----- Main code ---------------------------------------------------------*/
40
41 /* --- Matching --- */
42
43 static int n_mono(node *nn, const char *p, size_t sz)
44 {
45   node_mono *n = (node_mono *)nn;
46   unsigned map[UCHAR_MAX], imap[UCHAR_MAX];
47   const unsigned char *q = n->p;
48   int ch, i;
49
50   if (sz != n->len)
51     return (0);
52   memset(map, 0, sizeof(map));
53   memset(imap, 0, sizeof(imap));
54   while (*p) {
55     ch = *p++;
56     i = *q++;
57     if (!map[i]) {
58       if (imap[ch])
59         return (0);
60       map[i] = ch;
61       imap[ch] = 1;
62     } else if (map[i] != ch)
63       return (0);
64   }
65   return (1);
66 }
67
68 /* --- Node creation --- */
69
70 node *mono(const char *const *av)
71 {
72   unsigned char map[UCHAR_MAX];
73   unsigned max;
74   int ch;
75   const char *p;
76   unsigned char *q;
77
78   node_mono *n = xmalloc(sizeof(*n));
79   n->n.func = n_mono;
80   memset(map, UCHAR_MAX, sizeof(map));
81   max = 0;
82   p = av[0];
83   n->len = strlen(p);
84   q = xmalloc(n->len);
85   n->p = q;
86   while (*p) {
87     ch = *p++;
88     if (map[ch] >= max)
89       map[ch] = max++;
90     *q++ = map[ch];
91   }
92   return (&n->n);
93 }
94
95 /*----- That's all, folks -------------------------------------------------*/