xref: /aosp_15_r20/external/cronet/third_party/ced/src/util/case_insensitive_hash.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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