]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/server/zstring.c
need automake as a build-dep, even though we don't use most of it
[1ts-debian.git] / zephyr / server / zstring.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It contains the main loop of the Zephyr server
3  *
4  *      Created by:     Lucien W. Van Elsen
5  *
6  *      $Id$
7  *
8  *      Copyright (c) 1991 by the Massachusetts Institute of Technology.
9  *      For copying and distribution information, see the file
10  *      "mit-copyright.h". 
11  */
12
13 #include <zephyr/mit-copyright.h>
14 #include "zserver.h"
15
16 #ifndef lint
17 #ifndef SABER
18 static const char rcsid_zstring_c[] =
19 "$Id$";
20 #endif
21 #endif
22
23 static String *zhash[STRING_HASH_TABLE_SIZE];
24
25 int valid_utf8_p(const char* s)
26 {
27     ssize_t len;
28     int32_t uc;
29
30     while ((len = utf8proc_iterate((const unsigned char *)s, -1, &uc))) {
31         if (len <=0) return 0; /* Not valid UTF-8 encoding. */
32         if (!(utf8proc_codepoint_valid(uc))) return 0; /* Not valid unicode codepoint. */
33         if (uc == 0) return 1; /* NULL, we're done. */
34         s += len;
35     }
36     return 0; /* We shouldn't get here. */
37 }
38
39 static char *zdowncase(const char* s)
40 {
41     char *new_s, *p;
42
43     if (valid_utf8_p(s)) {
44         /* Use utf8proc if we're dealing with UTF-8.
45          * Rather than downcase, casefold and normalize to NFKC.
46          */
47         utf8proc_map((const unsigned char *)s, 0, (unsigned char **)&new_s,
48                      UTF8PROC_NULLTERM   | UTF8PROC_STABLE
49                      | UTF8PROC_CASEFOLD | UTF8PROC_COMPAT
50                      | UTF8PROC_COMPOSE);
51     } else {
52         /* If not, fall back to old methods. */
53         new_s = strsave(s);
54         p = new_s;
55         while(*p) {
56             if (isascii(*p) && isupper(*p))
57                 *p = tolower(*p);
58             p++;
59         }
60     }
61     return new_s;
62 }
63
64 String *
65 make_string(char *s,
66             int downcase)
67 {
68     char *new_s;
69     String *new_z,*hp;
70     int i;
71
72     if (downcase) {
73         new_s = zdowncase(s);
74     } else {
75         new_s = s;
76     }
77
78     new_z = find_string(new_s,0);
79     if (new_z != NULL) {
80         if (downcase)
81             free(new_s);
82         new_z->ref_count++;
83         return(new_z);
84     }
85
86     /* Initialize new String */
87
88     if (!downcase)
89         new_s = strsave(s);
90     new_z = (String *) malloc(sizeof(String));
91     new_z->string = new_s;
92     new_z->ref_count = 1;
93   
94     /* Add to beginning of hash table */
95     new_z->hash_val = hash(new_s);
96     i = new_z->hash_val % STRING_HASH_TABLE_SIZE;
97     hp = zhash[i];
98     new_z->next = hp;
99     if (hp != NULL)
100         hp->prev = new_z;
101     new_z->prev = NULL;
102     zhash[i] = new_z;
103
104     return new_z;
105 }
106
107 void
108 free_string(String *z)
109 {
110     if (z == (String *) NULL)
111         return;
112
113     z->ref_count--;
114     if (z->ref_count > 0)
115         return;
116
117     /* delete string completely */
118     if(z->prev == NULL)
119         zhash[hash(z->string) % STRING_HASH_TABLE_SIZE] = z->next;
120     else
121         z->prev->next = z->next;
122   
123     if (z->next != NULL)
124         z->next->prev = z->prev;
125
126     free(z->string);
127     free(z);
128 }
129
130 String *
131 find_string(char *s,
132             int downcase)
133 {
134     char *new_s;
135     String *z;
136
137     if (downcase) {
138         new_s = zdowncase(s);
139     } else {
140         new_s = s;
141     }
142
143     z = zhash[hash(new_s) % STRING_HASH_TABLE_SIZE];
144     while (z != NULL) {
145         if (strcmp(new_s, z->string) == 0)
146             break;
147         z = z->next;
148     }
149
150     if (downcase)
151         free(new_s);
152
153     return z;
154 }
155
156 int
157 comp_string(String *a,
158             String *b)
159 {
160     if (a->hash_val > b->hash_val)
161         return 1;
162     if (a->hash_val < b->hash_val)
163         return -1;
164     return strcmp(a->string,b->string);
165 }
166
167 void
168 print_string_table(FILE *f)
169 {
170     String *p;
171     int i;
172
173     for(i = 0; i < STRING_HASH_TABLE_SIZE; i++) {
174         p = zhash[i];
175         while (p != (String *) NULL) {
176             fprintf(f,"[%d] %s\n",p->ref_count,p->string);
177             p = p->next;
178         }
179     }
180 }
181
182 String *
183 dup_string(String *z)
184 {
185     z->ref_count++;
186     return z;
187 }
188