Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2014-2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef _ANDROID_UTILS_FASTSTRCMP_H__
     18 #define _ANDROID_UTILS_FASTSTRCMP_H__
     19 
     20 #include <ctype.h>
     21 #include <string.h>
     22 
     23 #ifndef __predict_true
     24 #define __predict_true(exp) __builtin_expect((exp) != 0, 1)
     25 #endif
     26 
     27 #ifdef __cplusplus
     28 
     29 // Optimized for instruction cache locality
     30 //
     31 // Template class fastcmp used to create more time-efficient str*cmp
     32 // functions by pre-checking the first character before resorting
     33 // to calling the underlying string function.  Profiled with a
     34 // measurable speedup when used in hot code.  Usage is of the form:
     35 //
     36 //  fastcmp<strncmp>(str1, str2, len)
     37 //
     38 // NB: use fasticmp for the case insensitive str*cmp functions.
     39 // NB: Returns boolean, do not use if expecting to check negative value.
     40 //     Thus not semantically identical to the expected function behavior.
     41 
     42 template <int (*cmp)(const char* l, const char* r, const size_t s)>
     43 static inline int fastcmp(const char* l, const char* r, const size_t s) {
     44     const ssize_t n = s;  // To help reject negative sizes, treat like zero
     45     return __predict_true(n > 0) &&
     46            ((*l != *r) || (__predict_true(n > 1) && cmp(l + 1, r + 1, n - 1)));
     47 }
     48 
     49 template <int (*cmp)(const char* l, const char* r, const size_t s)>
     50 static inline int fasticmp(const char* l, const char* r, const size_t s) {
     51     const ssize_t n = s;  // To help reject negative sizes, treat like zero
     52     return __predict_true(n > 0) &&
     53            ((tolower(*l) != tolower(*r)) || (__predict_true(n > 1) && cmp(l + 1, r + 1, n - 1)));
     54 }
     55 
     56 template <int (*cmp)(const void* l, const void* r, const size_t s)>
     57 static inline int fastcmp(const void* lv, const void* rv, const size_t s) {
     58     const char* l = static_cast<const char*>(lv);
     59     const char* r = static_cast<const char*>(rv);
     60     const ssize_t n = s;  // To help reject negative sizes, treat like zero
     61     return __predict_true(n > 0) &&
     62            ((*l != *r) || (__predict_true(n > 1) && cmp(l + 1, r + 1, n - 1)));
     63 }
     64 
     65 template <int (*cmp)(const char* l, const char* r)>
     66 static inline int fastcmp(const char* l, const char* r) {
     67     return (*l != *r) || (__predict_true(*l) && cmp(l + 1, r + 1));
     68 }
     69 
     70 template <int (*cmp)(const char* l, const char* r)>
     71 static inline int fasticmp(const char* l, const char* r) {
     72     return (tolower(*l) != tolower(*r)) || (__predict_true(*l) && cmp(l + 1, r + 1));
     73 }
     74 
     75 #endif
     76 
     77 #endif // _ANDROID_UTILS_FASTSTRCMP_H__
     78