1 // Copyright 2016 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 //////////////////////////////////////////////////////////////////////////////// 16 17 #ifndef UTIL_CASE_INSENSITIVE_HASH_H_ 18 #define UTIL_CASE_INSENSITIVE_HASH_H_ 19 20 #include <ctype.h> 21 #include <stddef.h> 22 #ifndef _MSC_VER 23 #include <strings.h> 24 #endif 25 26 #include <string> 27 28 #include "util/basictypes.h" 29 #include "util/string_util.h" 30 31 // Functors for hashing c-strings with case-insensitive semantics. 32 struct CStringCaseHash { operatorCStringCaseHash33 size_t operator()(const char *str) const { 34 unsigned long hash_val = 0; 35 while (*str) { 36 hash_val = 5*hash_val + tolower(*str); 37 str++; 38 } 39 return (size_t)hash_val; 40 } 41 }; 42 43 struct CStringCaseEqual { operatorCStringCaseEqual44 bool operator()(const char *str1, const char *str2) const { 45 return !base::strcasecmp(str1, str2); 46 } 47 }; 48 49 // These functors, in addition to being case-insensitive, ignore all 50 // non-alphanumeric characters. This is useful when we want all variants of 51 // a string -- where variants can differ in puncutation and whitespace -- to 52 // map to the same value. 53 struct CStringAlnumCaseHash { operatorCStringAlnumCaseHash54 size_t operator()(const char *str) const { 55 unsigned long hash_val = 0; 56 while (*str) { 57 if (isalnum(*str)) { 58 hash_val = 5*hash_val + tolower(*str); 59 } 60 str++; 61 } 62 return (size_t)hash_val; 63 } 64 }; 65 66 struct CStringAlnumCaseEqual { operatorCStringAlnumCaseEqual67 bool operator()(const char *str1, const char *str2) const { 68 while (true) { 69 // Skip until each pointer is pointing to an alphanumeric char or '\0' 70 while (!isalnum(*str1) && (*str1 != '\0')) { 71 str1++; 72 } 73 while (!isalnum(*str2) && (*str2 != '\0')) { 74 str2++; 75 } 76 if (tolower(*str1) != tolower(*str2)) { 77 return false; // mismatch on alphanumeric char or '\0' 78 } 79 if (*str1 == '\0') { // in which case *str2 must be '\0' as well 80 return true; // reached '\0' in both strings without mismatch 81 } 82 str1++; 83 str2++; 84 } 85 } 86 }; 87 88 #endif // UTIL_CASE_INSENSITIVE_HASH_H_ 89