LCOV - code coverage report
Current view: top level - common - stringutils.h (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core 2463e5ebed6d Lines: 51 51 100.0 %
Date: 2019-03-18 07:48:51 Functions: 27 27 100.0 %
Branches: 17 20 85.0 %

           Branch data     Line data    Source code
       1                 :            : /** @file stringutils.h
       2                 :            :  * @brief Various handy helpers which std::string really should provide.
       3                 :            :  */
       4                 :            : /* Copyright (C) 2004,2005,2006,2007,2008,2009,2010,2015 Olly Betts
       5                 :            :  *
       6                 :            :  * This program is free software; you can redistribute it and/or modify
       7                 :            :  * it under the terms of the GNU General Public License as published by
       8                 :            :  * the Free Software Foundation; either version 2 of the License, or
       9                 :            :  * (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This program is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :            :  * GNU General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU General Public License
      17                 :            :  * along with this program; if not, write to the Free Software
      18                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
      19                 :            :  */
      20                 :            : 
      21                 :            : #ifndef XAPIAN_INCLUDED_STRINGUTILS_H
      22                 :            : #define XAPIAN_INCLUDED_STRINGUTILS_H
      23                 :            : 
      24                 :            : #include <xapian/constinfo.h>
      25                 :            : 
      26                 :            : #include <algorithm>
      27                 :            : #include <string>
      28                 :            : #include <cstring>
      29                 :            : 
      30                 :            : /** Helper macro for STRINGIZE - the nested call is required because of how
      31                 :            :  *  # works in macros.
      32                 :            :  */
      33                 :            : #define STRINGIZE_(X) #X
      34                 :            : 
      35                 :            : /// The STRINGIZE macro converts its parameter into a string constant.
      36                 :            : #define STRINGIZE(X) STRINGIZE_(X)
      37                 :            : 
      38                 :            : /** Returns the length of a string constant.
      39                 :            :  *
      40                 :            :  *  We rely on concatenation of string literals to produce an error if this
      41                 :            :  *  macro is applied to something other than a string literal.
      42                 :            :  */
      43                 :            : #define CONST_STRLEN(S) (sizeof(S"") - 1)
      44                 :            : 
      45                 :            : inline bool
      46                 :         14 : startswith(const std::string & s, char pfx)
      47                 :            : {
      48 [ +  - ][ +  - ]:         14 :     return !s.empty() && s[0] == pfx;
      49                 :            : }
      50                 :            : 
      51                 :            : inline bool
      52                 :      74775 : startswith(const std::string & s, const char * pfx, size_t len)
      53                 :            : {
      54 [ +  + ][ +  + ]:      74775 :     return s.size() >= len && (std::memcmp(s.data(), pfx, len) == 0);
      55                 :            : }
      56                 :            : 
      57                 :            : inline bool
      58                 :        819 : startswith(const std::string & s, const char * pfx)
      59                 :            : {
      60                 :        819 :     return startswith(s, pfx, std::strlen(pfx));
      61                 :            : }
      62                 :            : 
      63                 :            : inline bool
      64                 :      73956 : startswith(const std::string & s, const std::string & pfx)
      65                 :            : {
      66                 :      73956 :     return startswith(s, pfx.data(), pfx.size());
      67                 :            : }
      68                 :            : 
      69                 :            : inline bool
      70                 :          3 : endswith(const std::string & s, char sfx)
      71                 :            : {
      72 [ +  - ][ +  + ]:          3 :     return !s.empty() && s[s.size() - 1] == sfx;
      73                 :            : }
      74                 :            : 
      75                 :            : inline bool
      76                 :        943 : endswith(const std::string & s, const char * sfx, size_t len)
      77                 :            : {
      78 [ +  + ][ +  + ]:        943 :     return s.size() >= len && (std::memcmp(s.data() + s.size() - len, sfx, len) == 0);
      79                 :            : }
      80                 :            : 
      81                 :            : inline bool
      82                 :         22 : endswith(const std::string & s, const char * sfx)
      83                 :            : {
      84                 :         22 :     return endswith(s, sfx, std::strlen(sfx));
      85                 :            : }
      86                 :            : 
      87                 :            : inline bool
      88                 :        921 : endswith(const std::string & s, const std::string & sfx)
      89                 :            : {
      90                 :        921 :     return endswith(s, sfx.data(), sfx.size());
      91                 :            : }
      92                 :            : 
      93                 :            : inline std::string::size_type
      94                 :    2894365 : common_prefix_length(const std::string &a, const std::string &b)
      95                 :            : {
      96                 :    2894365 :     std::string::size_type minlen = std::min(a.size(), b.size());
      97                 :            :     std::string::size_type common;
      98         [ +  + ]:   11926092 :     for (common = 0; common < minlen; ++common) {
      99         [ +  + ]:   11816088 :         if (a[common] != b[common]) break;
     100                 :            :     }
     101                 :    2894365 :     return common;
     102                 :            : }
     103                 :            : 
     104                 :            : // Like C's isXXXXX() but:
     105                 :            : //  (a) always work in the C locale
     106                 :            : //  (b) handle signed char as well as unsigned char
     107                 :            : //  (c) have a suitable signature for use as predicates with find_if()
     108                 :            : //  (d) add negated versions isnotXXXXX() which are useful as predicates
     109                 :            : 
     110                 :            : namespace Xapian {
     111                 :            :     namespace Internal {
     112                 :            :         const unsigned char HEX_MASK = 0x0f;
     113                 :            :         const unsigned char IS_UPPER = 0x10;
     114                 :            :         const unsigned char IS_ALPHA = 0x20; // NB Same as ASCII "case bit".
     115                 :            :         const unsigned char IS_DIGIT = 0x40;
     116                 :            :         const unsigned char IS_SPACE = 0x80;
     117                 :            :     }
     118                 :            : }
     119                 :            : 
     120                 :            : // FIXME: These functions assume ASCII or an ASCII compatible character set
     121                 :            : // such as ISO-8859-N or UTF-8.  EBCDIC would need some work (patches
     122                 :            : // welcome!)
     123                 :            : static_assert('\x20' == ' ', "character set isn't a superset of ASCII");
     124                 :            : 
     125                 :            : // Add explicit conversion to bool to prevent compiler warning from "aCC +w":
     126                 :            : // Warning (suggestion) 818: [...] # Type `int' is larger than type `bool',
     127                 :            : // truncation in value may result.
     128                 :            : 
     129                 :   44372536 : inline unsigned char C_tab_(char ch) {
     130                 :   44372536 :     const unsigned char * C_tab = Xapian::Internal::get_constinfo_()->C_tab;
     131                 :   44372536 :     return C_tab[static_cast<unsigned char>(ch)];
     132                 :            : }
     133                 :            : 
     134                 :        780 : inline bool C_isdigit(char ch) {
     135                 :            :     using namespace Xapian::Internal;
     136                 :        780 :     return bool(C_tab_(ch) & IS_DIGIT);
     137                 :            : }
     138                 :            : 
     139                 :        816 : inline bool C_isxdigit(char ch) {
     140                 :            :     using namespace Xapian::Internal;
     141                 :            :     // Include IS_DIGIT so '0' gives true.
     142                 :        816 :     return bool(C_tab_(ch) & (HEX_MASK|IS_DIGIT));
     143                 :            : }
     144                 :            : 
     145                 :      93436 : inline bool C_isupper(char ch) {
     146                 :            :     using namespace Xapian::Internal;
     147                 :      93436 :     return bool(C_tab_(ch) & IS_UPPER);
     148                 :            : }
     149                 :            : 
     150                 :      11133 : inline bool C_islower(char ch) {
     151                 :            :     using namespace Xapian::Internal;
     152                 :      11133 :     return (C_tab_(ch) & (IS_ALPHA|IS_UPPER)) == IS_ALPHA;
     153                 :            : }
     154                 :            : 
     155                 :      82020 : inline bool C_isalpha(char ch) {
     156                 :            :     using namespace Xapian::Internal;
     157                 :      82020 :     return bool(C_tab_(ch) & IS_ALPHA);
     158                 :            : }
     159                 :            : 
     160                 :   12392115 : inline bool C_isalnum(char ch) {
     161                 :            :     using namespace Xapian::Internal;
     162                 :   12392115 :     return bool(C_tab_(ch) & (IS_ALPHA|IS_DIGIT));
     163                 :            : }
     164                 :            : 
     165                 :   20124898 : inline bool C_isspace(char ch) {
     166                 :            :     using namespace Xapian::Internal;
     167                 :   20124898 :     return bool(C_tab_(ch) & IS_SPACE);
     168                 :            : }
     169                 :            : 
     170                 :        768 : inline bool C_isnotdigit(char ch) { return !C_isdigit(ch); }
     171                 :        768 : inline bool C_isnotxdigit(char ch) { return !C_isxdigit(ch); }
     172                 :        768 : inline bool C_isnotupper(char ch) { return !C_isupper(ch); }
     173                 :        768 : inline bool C_isnotlower(char ch) { return !C_islower(ch); }
     174                 :        768 : inline bool C_isnotalpha(char ch) { return !C_isalpha(ch); }
     175                 :        768 : inline bool C_isnotalnum(char ch) { return !C_isalnum(ch); }
     176                 :   10511902 : inline bool C_isnotspace(char ch) { return !C_isspace(ch); }
     177                 :            : 
     178                 :   11667188 : inline char C_tolower(char ch) {
     179                 :            :     using namespace Xapian::Internal;
     180                 :   11667188 :     return ch | (C_tab_(ch) & IS_ALPHA);
     181                 :            : }
     182                 :            : 
     183                 :         16 : inline char C_toupper(char ch) {
     184                 :            :     using namespace Xapian::Internal;
     185                 :         16 :     return ch &~ (C_tab_(ch) & IS_ALPHA);
     186                 :            : }
     187                 :            : 
     188                 :        134 : inline int hex_digit(char ch) {
     189                 :            :     using namespace Xapian::Internal;
     190                 :        134 :     return C_tab_(ch) & HEX_MASK;
     191                 :            : }
     192                 :            : 
     193                 :            : #endif // XAPIAN_INCLUDED_STRINGUTILS_H

Generated by: LCOV version 1.11