/* This file is part of the Project Athena Zephyr Notification System. * It contains the main loop of the Zephyr server * * Created by: Lucien W. Van Elsen * * $Id$ * * Copyright (c) 1991 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file * "mit-copyright.h". */ #include #include "zserver.h" #ifndef lint #ifndef SABER static const char rcsid_zstring_c[] = "$Id$"; #endif #endif static String *zhash[STRING_HASH_TABLE_SIZE]; static int valid_utf8_p(const char* s) { ssize_t len; int32_t uc; while ((len = utf8proc_iterate((const unsigned char *)s, -1, &uc))) { if (len <=0) return 0; /* Not valid UTF-8 encoding. */ if (!(utf8proc_codepoint_valid(uc))) return 0; /* Not valid unicode codepoint. */ if (uc == 0) return 1; /* NULL, we're done. */ s += len; } return 0; /* We shouldn't get here. */ } static char *zdowncase(const char* s) { unsigned char *new_s_u; /* Avoid strict aliasing violation */ char *new_s, *p; if (valid_utf8_p(s)) { /* Use utf8proc if we're dealing with UTF-8. * Rather than downcase, casefold and normalize to NFKC. */ utf8proc_map((const unsigned char *)s, 0, (unsigned char **)&new_s_u, UTF8PROC_NULLTERM | UTF8PROC_STABLE | UTF8PROC_CASEFOLD | UTF8PROC_COMPAT | UTF8PROC_COMPOSE); new_s = (char *)new_s_u; } else { /* If not, fall back to old methods. */ new_s = strsave(s); p = new_s; while(*p) { if (isascii(*p) && isupper(*p)) *p = tolower(*p); p++; } } return new_s; } String * make_string(char *s, int downcase) { char *new_s; String *new_z,*hp; int i; if (downcase) { new_s = zdowncase(s); } else { new_s = s; } new_z = find_string(new_s,0); if (new_z != NULL) { if (downcase) free(new_s); new_z->ref_count++; return(new_z); } /* Initialize new String */ if (!downcase) new_s = strsave(s); new_z = (String *) malloc(sizeof(String)); new_z->string = new_s; new_z->ref_count = 1; /* Add to beginning of hash table */ new_z->hash_val = hash(new_s); i = new_z->hash_val % STRING_HASH_TABLE_SIZE; hp = zhash[i]; new_z->next = hp; if (hp != NULL) hp->prev = new_z; new_z->prev = NULL; zhash[i] = new_z; return new_z; } void free_string(String *z) { if (z == (String *) NULL) return; z->ref_count--; if (z->ref_count > 0) return; /* delete string completely */ if(z->prev == NULL) zhash[hash(z->string) % STRING_HASH_TABLE_SIZE] = z->next; else z->prev->next = z->next; if (z->next != NULL) z->next->prev = z->prev; free(z->string); free(z); } String * find_string(char *s, int downcase) { char *new_s; String *z; if (downcase) { new_s = zdowncase(s); } else { new_s = s; } z = zhash[hash(new_s) % STRING_HASH_TABLE_SIZE]; while (z != NULL) { if (strcmp(new_s, z->string) == 0) break; z = z->next; } if (downcase) free(new_s); return z; } int comp_string(String *a, String *b) { if (a->hash_val > b->hash_val) return 1; if (a->hash_val < b->hash_val) return -1; return strcmp(a->string,b->string); } void print_string_table(FILE *f) { String *p; int i; for(i = 0; i < STRING_HASH_TABLE_SIZE; i++) { p = zhash[i]; while (p != (String *) NULL) { fprintf(f,"[%d] %s\n",p->ref_count,p->string); p = p->next; } } } String * dup_string(String *z) { z->ref_count++; return z; }