diff options
author | Eduardo Chappa <echappa@gmx.com> | 2013-02-03 00:59:38 -0700 |
---|---|---|
committer | Eduardo Chappa <echappa@gmx.com> | 2013-02-03 00:59:38 -0700 |
commit | 094ca96844842928810f14844413109fc6cdd890 (patch) | |
tree | e60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /imap/src/c-client/misc.c | |
download | alpine-094ca96844842928810f14844413109fc6cdd890.tar.xz |
Initial Alpine Version
Diffstat (limited to 'imap/src/c-client/misc.c')
-rw-r--r-- | imap/src/c-client/misc.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/imap/src/c-client/misc.c b/imap/src/c-client/misc.c new file mode 100644 index 00000000..4b789af8 --- /dev/null +++ b/imap/src/c-client/misc.c @@ -0,0 +1,475 @@ +/* ======================================================================== + * Copyright 1988-2006 University of Washington + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * + * ======================================================================== + */ + +/* + * Program: Miscellaneous utility routines + * + * Author: Mark Crispin + * Networks and Distributed Computing + * Computing & Communications + * University of Washington + * Administration Building, AG-44 + * Seattle, WA 98195 + * Internet: MRC@CAC.Washington.EDU + * + * Date: 5 July 1988 + * Last Edited: 6 December 2006 + * + * This original version of this file is + * Copyright 1988 Stanford University + * and was developed in the Symbolic Systems Resources Group of the Knowledge + * Systems Laboratory at Stanford University in 1987-88, and was funded by the + * Biomedical Research Technology Program of the NationalInstitutes of Health + * under grant number RR-00785. + */ + + +#include <ctype.h> +#include "c-client.h" + +/* Convert ASCII string to all uppercase + * Accepts: string pointer + * Returns: string pointer + * + * Don't use islower/toupper since this function must be ASCII only. + */ + +unsigned char *ucase (unsigned char *s) +{ + unsigned char *t; + /* if lowercase covert to upper */ + for (t = s; *t; t++) if ((*t >= 'a') && (*t <= 'z')) *t -= ('a' - 'A'); + return s; /* return string */ +} + + +/* Convert string to all lowercase + * Accepts: string pointer + * Returns: string pointer + * + * Don't use isupper/tolower since this function must be ASCII only. + */ + +unsigned char *lcase (unsigned char *s) +{ + unsigned char *t; + /* if uppercase covert to lower */ + for (t = s; *t; t++) if ((*t >= 'A') && (*t <= 'Z')) *t += ('a' - 'A'); + return s; /* return string */ +} + +/* Copy string to free storage + * Accepts: source string + * Returns: free storage copy of string + */ + +char *cpystr (const char *string) +{ + return string ? strcpy ((char *) fs_get (1 + strlen (string)),string) : NIL; +} + + +/* Copy text/size to free storage as sized text + * Accepts: destination sized text + * pointer to source text + * size of source text + * Returns: text as a char * + */ + +char *cpytxt (SIZEDTEXT *dst,char *text,unsigned long size) +{ + /* flush old space */ + if (dst->data) fs_give ((void **) &dst->data); + /* copy data in sized text */ + memcpy (dst->data = (unsigned char *) + fs_get ((size_t) (dst->size = size) + 1),text,(size_t) size); + dst->data[size] = '\0'; /* tie off text */ + return (char *) dst->data; /* convenience return */ +} + +/* Copy sized text to free storage as sized text + * Accepts: destination sized text + * source sized text + * Returns: text as a char * + */ + +char *textcpy (SIZEDTEXT *dst,SIZEDTEXT *src) +{ + /* flush old space */ + if (dst->data) fs_give ((void **) &dst->data); + /* copy data in sized text */ + memcpy (dst->data = (unsigned char *) + fs_get ((size_t) (dst->size = src->size) + 1), + src->data,(size_t) src->size); + dst->data[dst->size] = '\0'; /* tie off text */ + return (char *) dst->data; /* convenience return */ +} + + +/* Copy stringstruct to free storage as sized text + * Accepts: destination sized text + * source stringstruct + * Returns: text as a char * + */ + +char *textcpystring (SIZEDTEXT *text,STRING *bs) +{ + unsigned long i = 0; + /* clear old space */ + if (text->data) fs_give ((void **) &text->data); + /* make free storage space in sized text */ + text->data = (unsigned char *) fs_get ((size_t) (text->size = SIZE (bs)) +1); + while (i < text->size) text->data[i++] = SNX (bs); + text->data[i] = '\0'; /* tie off text */ + return (char *) text->data; /* convenience return */ +} + + +/* Copy stringstruct from offset to free storage as sized text + * Accepts: destination sized text + * source stringstruct + * offset into stringstruct + * size of source text + * Returns: text as a char * + */ + +char *textcpyoffstring (SIZEDTEXT *text,STRING *bs,unsigned long offset, + unsigned long size) +{ + unsigned long i = 0; + /* clear old space */ + if (text->data) fs_give ((void **) &text->data); + SETPOS (bs,offset); /* offset the string */ + /* make free storage space in sized text */ + text->data = (unsigned char *) fs_get ((size_t) (text->size = size) + 1); + while (i < size) text->data[i++] = SNX (bs); + text->data[i] = '\0'; /* tie off text */ + return (char *) text->data; /* convenience return */ +} + +/* Returns index of rightmost bit in word + * Accepts: pointer to a 32 bit value + * Returns: -1 if word is 0, else index of rightmost bit + * + * Bit is cleared in the word + */ + +unsigned long find_rightmost_bit (unsigned long *valptr) +{ + unsigned long value = *valptr; + unsigned long bit = 0; + if (!(value & 0xffffffff)) return 0xffffffff; + /* binary search for rightmost bit */ + if (!(value & 0xffff)) value >>= 16, bit += 16; + if (!(value & 0xff)) value >>= 8, bit += 8; + if (!(value & 0xf)) value >>= 4, bit += 4; + if (!(value & 0x3)) value >>= 2, bit += 2; + if (!(value & 0x1)) value >>= 1, bit += 1; + *valptr ^= (1 << bit); /* clear specified bit */ + return bit; +} + + +/* Return minimum of two integers + * Accepts: integer 1 + * integer 2 + * Returns: minimum + */ + +long min (long i,long j) +{ + return ((i < j) ? i : j); +} + + +/* Return maximum of two integers + * Accepts: integer 1 + * integer 2 + * Returns: maximum + */ + +long max (long i,long j) +{ + return ((i > j) ? i : j); +} + +/* Search, case-insensitive for ASCII characters + * Accepts: base string + * length of base string + * pattern string + * length of pattern string + * Returns: T if pattern exists inside base, else NIL + */ + +long search (unsigned char *base,long basec,unsigned char *pat,long patc) +{ + long i,j,k; + int c; + unsigned char mask[256]; + static unsigned char alphatab[256] = { + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, + 223,223,223,223,223,223,223,223,223,223,223,255,255,255,255,255, + 255,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, + 223,223,223,223,223,223,223,223,223,223,223,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 + }; + /* validate arguments */ + if (base && (basec > 0) && pat && (basec >= patc)) { + if (patc <= 0) return T; /* empty pattern always succeeds */ + memset (mask,0,256); /* initialize search validity mask */ + for (i = 0; i < patc; i++) if (!mask[c = pat[i]]) { + /* mark single character if non-alphabetic */ + if (alphatab[c] & 0x20) mask[c] = T; + /* else mark both cases */ + else mask[c & 0xdf] = mask[c | 0x20] = T; + } + /* Boyer-Moore type search */ + for (i = --patc; i < basec; i += (mask[c] ? 1 : (j + 1))) + for (j = patc,c = base[k = i]; !((c ^ pat[j]) & alphatab[c]); + j--,c = base[--k]) + if (!j) return T; /* found a match! */ + } + return NIL; /* pattern not found */ +} + +/* Boyer-Moore string search + * Accepts: base string + * length of base string + * pattern string + * length of pattern string + * Returns: T if pattern exists inside base, else NIL + */ + +long ssearch (unsigned char *base,long basec,unsigned char *pat,long patc) +{ + long i,j,k; + int c; + unsigned char mask[256]; + /* validate arguments */ + if (base && (basec > 0) && pat && (basec >= patc)) { + if (patc <= 0) return T; /* empty pattern always succeeds */ + memset (mask,0,256); /* initialize search validity mask */ + for (i = 0; i < patc; i++) mask[pat[i]] = T; + /* Boyer-Moore type search */ + for (i = --patc, c = pat[i]; i < basec; i += (mask[c] ? 1 : (j + 1))) + for (j = patc,c = base[k = i]; (c == pat[j]); j--,c = base[--k]) + if (!j) return T; /* found a match! */ + } + return NIL; /* pattern not found */ +} + +/* Create a hash table + * Accepts: size of new table (note: should be a prime) + * Returns: hash table + */ + +HASHTAB *hash_create (size_t size) +{ + size_t i = sizeof (size_t) + size * sizeof (HASHENT *); + HASHTAB *ret = (HASHTAB *) memset (fs_get (i),0,i); + ret->size = size; + return ret; +} + + +/* Destroy hash table + * Accepts: hash table + */ + +void hash_destroy (HASHTAB **hashtab) +{ + if (*hashtab) { + hash_reset (*hashtab); /* reset hash table */ + fs_give ((void **) hashtab); + } +} + + +/* Reset hash table + * Accepts: hash table + */ + +void hash_reset (HASHTAB *hashtab) +{ + size_t i; + HASHENT *ent,*nxt; + /* free each hash entry */ + for (i = 0; i < hashtab->size; i++) if (ent = hashtab->table[i]) + for (hashtab->table[i] = NIL; ent; ent = nxt) { + nxt = ent->next; /* get successor */ + fs_give ((void **) &ent); /* flush this entry */ + } +} + +/* Calculate index into hash table + * Accepts: hash table + * entry name + * Returns: index + */ + +unsigned long hash_index (HASHTAB *hashtab,char *key) +{ + unsigned long i,ret; + /* polynomial of letters of the word */ + for (ret = 0; i = (unsigned int) *key++; ret += i) ret *= HASHMULT; + return ret % (unsigned long) hashtab->size; +} + + +/* Look up name in hash table + * Accepts: hash table + * key + * Returns: associated data + */ + +void **hash_lookup (HASHTAB *hashtab,char *key) +{ + HASHENT *ret; + for (ret = hashtab->table[hash_index (hashtab,key)]; ret; ret = ret->next) + if (!strcmp (key,ret->name)) return ret->data; + return NIL; +} + +/* Add entry to hash table + * Accepts: hash table + * key + * associated data + * number of extra data slots + * Returns: hash entry + * Caller is responsible for ensuring that entry isn't already in table + */ + +HASHENT *hash_add (HASHTAB *hashtab,char *key,void *data,long extra) +{ + unsigned long i = hash_index (hashtab,key); + size_t j = sizeof (HASHENT) + (extra * sizeof (void *)); + HASHENT *ret = (HASHENT *) memset (fs_get (j),0,j); + ret->next = hashtab->table[i];/* insert as new head in this index */ + ret->name = key; /* set up hash key */ + ret->data[0] = data; /* and first data */ + return hashtab->table[i] = ret; +} + + +/* Look up name in hash table + * Accepts: hash table + * key + * associated data + * number of extra data slots + * Returns: associated data + */ + +void **hash_lookup_and_add (HASHTAB *hashtab,char *key,void *data,long extra) +{ + HASHENT *ret; + unsigned long i = hash_index (hashtab,key); + size_t j = sizeof (HASHENT) + (extra * sizeof (void *)); + for (ret = hashtab->table[i]; ret; ret = ret->next) + if (!strcmp (key,ret->name)) return ret->data; + ret = (HASHENT *) memset (fs_get (j),0,j); + ret->next = hashtab->table[i];/* insert as new head in this index */ + ret->name = key; /* set up hash key */ + ret->data[0] = data; /* and first data */ + return (hashtab->table[i] = ret)->data; +} + +/* Convert two hex characters into byte + * Accepts: char for high nybble + * char for low nybble + * Returns: byte + * + * Arguments must be isxdigit validated + */ + +unsigned char hex2byte (unsigned char c1,unsigned char c2) +{ + /* merge the two nybbles */ + return ((c1 -= (isdigit (c1) ? '0' : ((c1 <= 'Z') ? 'A' : 'a') - 10)) << 4) + + (c2 - (isdigit (c2) ? '0' : ((c2 <= 'Z') ? 'A' : 'a') - 10)); +} + + +/* Compare two unsigned longs + * Accepts: first value + * second value + * Returns: -1 if l1 < l2, 0 if l1 == l2, 1 if l1 > l2 + */ + +int compare_ulong (unsigned long l1,unsigned long l2) +{ + if (l1 < l2) return -1; + if (l1 > l2) return 1; + return 0; +} + + +/* Compare two unsigned chars, case-independent + * Accepts: first value + * second value + * Returns: -1 if c1 < c2, 0 if c1 == c2, 1 if c1 > c2 + * + * Don't use isupper/tolower since this function must be ASCII only. + */ + +int compare_uchar (unsigned char c1,unsigned char c2) +{ + return compare_ulong (((c1 >= 'A') && (c1 <= 'Z')) ? c1 + ('a' - 'A') : c1, + ((c2 >= 'A') && (c2 <= 'Z')) ? c2 + ('a' - 'A') : c2); +} + +/* Compare two case-independent ASCII strings + * Accepts: first string + * second string + * Returns: -1 if s1 < s2, 0 if s1 == s2, 1 if s1 > s2 + */ + +int compare_cstring (unsigned char *s1,unsigned char *s2) +{ + int i; + if (!s1) return s2 ? -1 : 0; /* empty string cases */ + else if (!s2) return 1; + for (; *s1 && *s2; s1++,s2++) if (i = (compare_uchar (*s1,*s2))) return i; + if (*s1) return 1; /* first string is longer */ + return *s2 ? -1 : 0; /* second string longer : strings identical */ +} + + +/* Compare case-independent string with sized text + * Accepts: first string + * sized text + * Returns: -1 if s1 < s2, 0 if s1 == s2, 1 if s1 > s2 + */ + +int compare_csizedtext (unsigned char *s1,SIZEDTEXT *s2) +{ + int i; + unsigned char *s; + unsigned long j; + if (!s1) return s2 ? -1 : 0; /* null string cases */ + else if (!s2) return 1; + for (s = (char *) s2->data,j = s2->size; *s1 && j; ++s1,++s,--j) + if (i = (compare_uchar (*s1,*s))) return i; + if (*s1) return 1; /* first string is longer */ + return j ? -1 : 0; /* second string longer : strings identical */ +} |