1 /*
2 
3   ----------------------------------------------------
4   httpry - HTTP logging and information retrieval tool
5   ----------------------------------------------------
6 
7   Copyright (c) 2005-2014 Jason Bittel <jason.bittel@gmail.com>
8 
9 */
10 
11 #include <ctype.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include "error.h"
16 
17 /* Strip leading and trailing spaces from parameter string, modifying
18    the string in place and returning a pointer to the (potentially)
19    new starting point */
str_strip_whitespace(char * str)20 char *str_strip_whitespace(char *str) {
21         size_t len = strlen(str);
22 
23 #ifdef DEBUG
24         ASSERT(str);
25         ASSERT(strlen(str) > 0);
26 #endif
27 
28         while (isspace(*str)) str++;
29         while (len && isspace(*(str + len - 1)))
30                 *(str + (len--) - 1) = '\0';
31 
32         return str;
33 }
34 
35 /* Convert the paramter string to lowercase */
str_tolower(char * str)36 char *str_tolower(char *str) {
37         char *c;
38 
39 #ifdef DEBUG
40         ASSERT(str);
41         ASSERT(strlen(str) > 0);
42 #endif
43 
44         for (c = str; *c != '\0'; c++) {
45                 *c = tolower(*c);
46         }
47 
48         return str;
49 }
50 
51 /* Compare two strings, ignoring the case of str1 and
52    assuming str2 is lowercase. Break if we find a string
53    terminator in str2 and consider it a match as str1
54    will not always have a string terminator. */
str_compare(const char * str1,const char * str2)55 int str_compare(const char *str1, const char *str2) {
56 
57 #ifdef DEBUG
58         ASSERT(str2);
59         ASSERT(strlen(str2) > 0);
60         ASSERT(str1 != str2);
61 #endif
62 
63         while (tolower(*str1) == *str2) {
64                 str1++;
65                 str2++;
66                 if (*str2 == '\0') return 0;
67         }
68 
69         return tolower(*str1) - *str2;
70 }
71 
72 /* Copy at most len characters from src to dest, guaranteeing
73    dest will be properly terminated. Returns the total number of
74    characters copied, not including the string terminator. */
str_copy(char * dest,const char * src,size_t len)75 int str_copy(char *dest, const char *src, size_t len) {
76         const char *start = dest;
77 
78         if (len > 0) {
79                 while ((*src != '\0') && --len) {
80                         *dest++ = *src++;
81                 }
82                 *dest = '\0';
83         }
84 
85         return dest - start;
86 }
87 
88 /* Wrapper function around str_copy() that first allocates
89    memory for the destination string and then copies the
90    parameter string into it. */
str_duplicate(const char * str)91 char *str_duplicate(const char *str) {
92         char *new;
93         size_t len = strlen(str);
94 
95         if ((new = malloc(len + 1)) == NULL)
96                 return NULL;
97 
98 #ifdef DEBUG
99         ASSERT(str_copy(new, str, len + 1) <= (len + 1));
100 #else
101         str_copy(new, str, len + 1);
102 #endif
103 
104         return new;
105 }
106 
107 /* Implementation of Jenkins's One-at-a-Time hash, as described on
108    this page: http://www.burtleburtle.net/bob/hash/doobs.html */
hash_str(char * str,unsigned int hashsize)109 unsigned int hash_str(char *str, unsigned int hashsize) {
110         unsigned long int hash;
111 
112 #ifdef DEBUG
113         ASSERT(str);
114         ASSERT(strlen(str) > 0);
115 #endif
116 
117         for (hash = 0; *str != '\0'; str++) {
118                 hash += tolower(*str);
119                 hash += (hash << 10);
120                 hash ^= (hash >> 6);
121         }
122 
123         hash += (hash << 3);
124         hash ^= (hash >> 11);
125         hash += (hash << 15);
126 
127         /* Restrict hash value to a maximum of hashsize;
128            hashsize must be a power of 2 */
129         return (unsigned int) (hash & (hashsize - 1));
130 }
131