LCOV - code coverage report
Current view: top level - src - misc.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 80 108 74.1 %
Date: 2019-01-29 11:06:41 Functions: 15 20 75.0 %

          Line data    Source code
       1             : 
       2             : //////////////////////////////////////////////////////////////////////
       3             : //
       4             : //  FILE:       misc.h
       5             : //              Miscellaneous routines (File I/O, etc)
       6             : //
       7             : //  Part of:    Scid (Shane's Chess Information Database)
       8             : //  Version:    3.5
       9             : //
      10             : //  Notice:     Copyright (c) 2001-2003  Shane Hudson.  All rights reserved.
      11             : //              Copyright (C) 2015  Fulvio Benini
      12             : //
      13             : //  Author:     Shane Hudson (sgh@users.sourceforge.net)
      14             : //
      15             : //////////////////////////////////////////////////////////////////////
      16             : 
      17             : 
      18             : #ifndef SCID_MISC_H
      19             : #define SCID_MISC_H
      20             : 
      21             : #include "common.h"
      22             : #include <algorithm>
      23             : #include <string>
      24             : #include <cstring>
      25             : #include <stdio.h>
      26             : #include <ctype.h>   // For isspace(), etc
      27             : #include <cstdlib>
      28             : #include <vector>
      29             : 
      30             : /**
      31             :  * class StrRange - parse a string interpreting its content as 1 or 2 integers
      32             :  *                  separated by whitespace.
      33             :  * The integers represent the min and max value of a range.
      34             :  * If only one integer is provided it will represent both the min and max value.
      35             :  */
      36             : class StrRange {
      37             : protected:
      38             :         long min_;
      39             :         long max_;
      40             : 
      41             : protected:
      42             :         StrRange()
      43             :         : min_(0), max_(0) {}
      44             : 
      45             : public:
      46             :         explicit StrRange(const char* range) {
      47             :                 char* next;
      48             :                 min_ = std::strtol(range, &next, 10);
      49             :                 char* end;
      50             :                 max_ = std::strtol(next, &end, 10);
      51             :                 if (next == end) max_ = min_;
      52             :                 if (min_ > max_) std::swap(min_, max_);
      53             :         }
      54             : 
      55             :         /// @returns true if @e val is >= min_ and <= max_
      56             :         bool inRange(long val) const {
      57             :                 if (val < min_ || val > max_) return false;
      58             :                 return true;
      59             :         }
      60             : };
      61             : 
      62             : 
      63             : class Progress {
      64             : public:
      65             :         struct Impl {
      66             :                 virtual ~Impl() {}
      67             :                 virtual bool report(size_t done, size_t total, const char* msg) = 0;
      68             :         };
      69             : 
      70          52 :         Progress(Impl* f = NULL) : f_(f) {}
      71             :         Progress(const Progress&);
      72             :         Progress& operator=(const Progress&);
      73          52 :         ~Progress() { delete f_; }
      74             : 
      75          11 :         bool report(size_t done, size_t total) const {
      76          11 :                 return operator()(done, total);
      77             :         }
      78          28 :         bool operator()(size_t done, size_t total, const char* msg = NULL) const {
      79          28 :                 if (f_) return f_->report(done, total, msg);
      80          28 :                 return true;
      81             :         }
      82             : 
      83             : private:
      84             :         Impl* f_;
      85             : };
      86             : 
      87             : 
      88             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      89             : // strGetFilterOp:
      90             : //    Converts a string value to a filter operation value.
      91             : enum filterOpT { FILTEROP_AND, FILTEROP_OR, FILTEROP_RESET };
      92             : 
      93             : inline filterOpT strGetFilterOp (const char * str)
      94             : {
      95             :     switch (*str) {
      96             :         // AND:
      97             :         case 'A': case 'a': case '0': return FILTEROP_AND;
      98             :         // OR:
      99             :         case 'O': case 'o': case '1': return FILTEROP_OR;
     100             :         // RESET:
     101             :         case 'R': case 'r': case '2': return FILTEROP_RESET;
     102             :     }
     103             :     // Default is RESET.
     104             :     return FILTEROP_RESET;
     105             : }
     106             : 
     107             : // ECO string routines
     108             : //
     109             : void eco_ToString (ecoT ecoCode, char * ecoStr, bool extensions = true);
     110             : inline void eco_ToBasicString (ecoT ecoCode, char * ecoStr) {
     111             :     eco_ToString (ecoCode, ecoStr, false);
     112             : }
     113          31 : inline void eco_ToExtendedString (ecoT ecoCode, char * ecoStr) {
     114          31 :     eco_ToString (ecoCode, ecoStr, true);
     115          31 : }
     116             : ecoT eco_FromString (const char * ecoStr);
     117             : ecoT eco_LastSubCode (ecoT ecoCode);
     118             : ecoT eco_BasicCode (ecoT ecoCode);
     119             : ecoT eco_Reduce(ecoT eco);
     120             : 
     121             : // String routines. Some are identical to ANSI standard functions, but
     122             : //      I have included them:
     123             : //      (a) to keep nice consistent naming conventions, e.g. strCopy.
     124             : //      (b) so stats can easily be kept by modifying the functions.
     125             : //      (c) so some can be made inline for speed if necessary.
     126             : 
     127    18029458 : inline uint32_t strStartHash(const char* str) {
     128    18029458 :         ASSERT(str != 0);
     129    18029458 :         const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
     130             : 
     131    18029458 :         uint32_t tmp = static_cast<unsigned char>(tolower(*s));
     132    18029458 :         uint32_t result = tmp << 24;
     133    18029458 :         if (*s == '\0') return result;
     134    17993448 :         tmp = static_cast<unsigned char>(tolower(*++s));
     135    17993448 :         result += tmp << 16;
     136    17993448 :         if (*s == '\0') return result;
     137    17920388 :         tmp = static_cast<unsigned char>(tolower(*++s));
     138    17920388 :         result += tmp << 8;
     139    17920388 :         if (*s == '\0') return result;
     140    17866108 :         result += static_cast<unsigned char>(tolower(*++s));
     141    17866108 :         return result;
     142             : }
     143             : 
     144             : char * strDuplicate (const char * str);
     145             : 
     146             : void   strCopyExclude (char * target, const char * original,
     147             :                        const char * excludeChars);
     148             : char * strAppend (char * target, const char * extra);
     149             : uint   strPad (char * target, const char * orig, int length, char pad);
     150             : const char * strFirstChar (const char * target, char matchChar);
     151             : const char * strLastChar (const char * target, char matchChar);
     152             : void   strStrip (char * str, char ch);
     153             : 
     154             : const char * strTrimLeft (const char * target, const char * trimChars);
     155             : inline const char * strTrimLeft (const char * target) {
     156             :     return strTrimLeft (target, " \t\r\n");
     157             : }
     158             : uint   strTrimSuffix (char * target, char suffixChar);
     159             : void   strTrimDate (char * str);
     160             : void   strTrimMarkCodes (char * str);
     161             : void   strTrimMarkup (char * str);
     162             : const char * strFirstWord (const char * str);
     163             : const char * strNextWord (const char * str);
     164             : 
     165             : // strPlural:
     166             : //    Returns the empty string if its parameter is 1, or "s" otherwise.
     167             : inline const char *
     168             : strPlural (uint x) {
     169             :     return (x == 1 ? "" : "s");
     170             : }
     171             : 
     172             : bool   strIsUnknownName (const char * str);
     173             : 
     174             : // strIsSurnameOnly: returns true if a string appears to only
     175             : //    contain a surname.
     176             : bool   strIsSurnameOnly (const char * name);
     177             : 
     178             : bool   strGetBoolean (const char * str);
     179             : 
     180             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     181             : // strGetInteger():
     182             : //    Extracts a signed base-10 value from a string.
     183             : //    Defaults to zero (as strtol does) for non-numeric strings.
     184             : inline int
     185           0 : strGetInteger(const char * str)
     186             : {
     187           0 :         return std::strtol(str, NULL, 10);
     188             : }
     189             : 
     190             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     191             : // strGetUnsigned():
     192             : //    Extracts an unsigned base-10 value from a string.
     193             : //    Defaults to zero (as strtoul does) for non-numeric strings.
     194             : //
     195      347554 : inline uint32_t strGetUnsigned(const char* str) {
     196      347554 :         ASSERT(str != NULL);
     197      347554 :         return static_cast<uint32_t>(std::strtoul(str, NULL, 10));
     198             : }
     199             : 
     200    19146478 : inline int strCaseCompare(const char* str1, const char* str2) {
     201    19146478 :         ASSERT(str1 != NULL && str2 != NULL);
     202    19146478 :         const unsigned char* s1 = reinterpret_cast<const unsigned char*>(str1);
     203    19146478 :         const unsigned char* s2 = reinterpret_cast<const unsigned char*>(str2);
     204             :         int c1, c2;
     205     2499959 :         do {
     206    21646437 :                 c1 = tolower(*s1++);
     207    21646437 :                 c2 = tolower(*s2++);
     208    21646437 :                 if (c1 == '\0')
     209      194600 :                         break;
     210    21451837 :         } while (c1 == c2);
     211             : 
     212    19146478 :         return c1 - c2;
     213             : }
     214             : 
     215      171540 : inline int strCompareRound(const char* str1, const char* str2) {
     216      171540 :         ASSERT(str1 != NULL && str2 != NULL);
     217      171540 :         uint32_t a = strGetUnsigned(str1);
     218      171540 :         uint32_t b = strGetUnsigned(str2);
     219      171540 :         if (a == b)
     220       42952 :                 return strCaseCompare(str1, str2);
     221      128588 :         return (a < b) ? -1 : 1;
     222             : }
     223             : 
     224           0 : inline bool strEqual(const char* str1, const char* str2) {
     225           0 :         ASSERT(str1 != NULL && str2 != NULL);
     226           0 :         return (std::strcmp(str1, str2) == 0);
     227             : }
     228             : 
     229             : void   strGetIntegers (const char * str, int * results, uint nResults);
     230             : void   strGetUnsigneds (const char * str, uint * results, uint nResults);
     231             : resultT strGetResult (const char * str);
     232             : 
     233             : typedef uint flagT;
     234             : const flagT FLAG_EMPTY = 0;
     235             : const flagT FLAG_YES = 1;
     236             : const flagT FLAG_NO = 2;
     237             : const flagT FLAG_BOTH = 3;
     238             : inline bool flag_Yes (flagT t) { return (t & FLAG_YES); }
     239             : inline bool flag_No (flagT t) { return (t & FLAG_NO); }
     240             : flagT  strGetFlag (const char * str);
     241             : 
     242             : squareT strGetSquare (const char * str);
     243             : 
     244             : inline uint
     245             : strTrimFileSuffix (char * target) { return strTrimSuffix (target, '.'); }
     246             : 
     247             : inline const char *
     248             : strFileSuffix (const char * target) { return strLastChar (target, '.'); }
     249             : 
     250             : 
     251             : 
     252             : int strUniqueExactMatch (const char * keyStr, const char ** strTable,
     253             :                          bool exact);
     254             : 
     255             : inline int strUniqueMatch (const char * keyStr, const char ** strTable) {
     256             :     return strUniqueExactMatch (keyStr, strTable, false);
     257             : }
     258             : inline int strExactMatch (const char * keyStr, const char ** strTable) {
     259             :     return strUniqueExactMatch (keyStr, strTable, true);
     260             : }
     261             : 
     262             : inline bool
     263         220 : strContainsChar (const char * str, char ch)
     264             : {
     265         375 :     while (*str) {
     266         185 :         if (*str == ch) { return true; }
     267         155 :         str++;
     268             :     }
     269          35 :     return false;
     270             : }
     271             : 
     272             : // WARNING: Avoid this function!
     273             : // Considering that the sign of a char is implementation-defined [3.9.1], the
     274             : // int conversion ("[4.7.3] If the destination type is signed, the value is
     275             : // unchanged if it can be represented in the destination type") can yield
     276             : // different results on different architectures or compilers.
     277             : // A better alternative is the standard function strcmp() that returns the
     278             : // difference between the values of the first pair of characters (both
     279             : // interpreted as unsigned char) that differ in the strings being compared.
     280    88664938 : inline int strCompare(const char* s1, const char* s2)
     281             : {
     282    88664938 :     ASSERT (s1 != NULL  &&  s2 != NULL);
     283             :     while (1) {
     284   665591162 :         if (*s1 != *s2) {
     285    83796146 :             return ((int) *s1) - ((int) *s2);
     286             :         }
     287   293331904 :         if (*s1 == 0)
     288     4868792 :             break;
     289   288463112 :         s1++; s2++;
     290             :     }
     291     4868792 :     return 0;
     292             : }
     293             : 
     294             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     295             : // strCopy(): same as strcpy().
     296             : //
     297             : inline void
     298           0 : strCopy (char * target, const char * original)
     299             : {
     300           0 :     ASSERT (target != NULL  &&  original != NULL);
     301           0 :     while (*original != 0) {
     302           0 :         *target = *original;
     303           0 :         target++;
     304           0 :         original++;
     305             :     }
     306           0 :     *target = 0;
     307           0 : }
     308             : 
     309             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     310             : // strPrefix():
     311             : //       Returns the length of the common prefix of two strings.
     312             : //
     313             : inline uint
     314           1 : strPrefix (const char * s1, const char * s2)
     315             : {
     316           1 :     ASSERT (s1 != NULL  &&  s2 != NULL);
     317           1 :     uint count = 0;
     318          13 :     while (*s1 == *s2) {
     319           6 :         if (*s1 == 0) { // seen end of string, strings are identical
     320           0 :             return count;
     321             :         }
     322           6 :         count++; s1++; s2++;
     323             :     }
     324           1 :     return count;
     325             : }
     326             : 
     327             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     328             : // strIsPrefix():
     329             : //      Returns true if the prefix string is a prefix of longStr.
     330             : inline bool
     331           0 : strIsPrefix (const char * prefix, const char * longStr)
     332             : {
     333           0 :     while (*prefix) {
     334           0 :         if (*longStr == 0) { return false; }
     335           0 :         if (*prefix != *longStr) { return false; }
     336           0 :         prefix++;
     337           0 :         longStr++;
     338             :     }
     339           0 :     return true;
     340             : }
     341             : 
     342             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     343             : // strIsCasePrefix():
     344             : //      Returns true if the prefix string is a case-insensitive
     345             : //      prefix of longStr.
     346             : inline bool
     347           0 : strIsCasePrefix (const char * prefix, const char * longStr)
     348             : {
     349             :     typedef unsigned char U;
     350           0 :     while (*prefix) {
     351           0 :         if (*longStr == 0) { return false; }
     352           0 :         if (tolower(U(*prefix)) != tolower(U(*longStr))) { return false; }
     353           0 :         prefix++;
     354           0 :         longStr++;
     355             :     }
     356           0 :     return true;
     357             : }
     358             : 
     359             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     360             : // strIsAlphaPrefix():
     361             : //      Returns true if the prefix string is a prefix of longStr.
     362             : //      Unlike strIsPrexix(), this version is case-insensitive and
     363             : //      spaces are ignored.
     364             : //      Example: strIsAlphaPrefix ("smith,j", "Smith, John") == true.
     365             : inline bool
     366             : strIsAlphaPrefix (const char * prefix, const char * longStr)
     367             : {
     368             :     typedef unsigned char U;
     369             :     while (*prefix) {
     370             :         while (*prefix == ' ') { prefix++; }
     371             :         while (*longStr == ' ') { longStr++; }
     372             :         if (*longStr == 0) { return false; }
     373             :         if (tolower(U(*prefix)) != tolower(U(*longStr))) { return false; }
     374             :         prefix++;
     375             :         longStr++;
     376             :     }
     377             :     return true;
     378             : }
     379             : 
     380             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     381             : // strContains():
     382             : //      Returns true if longStr contains an occurrence of keyStr,
     383             : //      case-sensitive and NOT ignoring any characters such as spaces.
     384             : inline bool
     385             : strContains (const char * longStr, const char * keyStr)
     386             : {
     387             :     while (*longStr) {
     388             :         if (strIsPrefix (keyStr, longStr)) { return true; }
     389             :         longStr++;
     390             :     }
     391             :     return false;
     392             : }
     393             : 
     394             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     395             : // strAlphaContains():
     396             : //      Returns true if longStr contains an occurrence of keyStr,
     397             : //      case-insensitive and ignoring spaces.
     398             : //      Example: strAlphaContains ("Smith, John", "th,j") == true.
     399             : //
     400             : inline bool
     401             : strAlphaContains (const char * longStr, const char * keyStr)
     402             : {
     403             :     while (*longStr) {
     404             :         if (strIsAlphaPrefix (keyStr, longStr)) { return true; }
     405             :         longStr++;
     406             :     }
     407             :     return false;
     408             : }
     409             : 
     410             : inline uint
     411     3435078 : strLength (const char * str)
     412             : {
     413     3435078 :     ASSERT(str != NULL);
     414     3435078 :     uint len = 0;
     415    47037201 :     while (*str != 0) { len++; str++; }
     416     3435078 :     return len;
     417             : }
     418             : 
     419             : 
     420             : //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     421             : // strTrimRight():
     422             : //      Trims the provided string in-place, removing the
     423             : //      end characters that match the trimChars.
     424             : //      Returns the number of characters trimmed.
     425             : //      E.g., strTrimRight("abcyzyz", "yz") would leave the string
     426             : //      as "abc".
     427          26 : inline void strTrimRight(char* target, const char* trimChars, size_t nTrimCh) {
     428          26 :         const char* endTrim = trimChars + nTrimCh;
     429          26 :         size_t iCh = strlen(target);
     430         102 :         for (; iCh > 0; --iCh) {
     431          58 :                 if (std::find(trimChars, endTrim, target[iCh - 1]) == endTrim)
     432          20 :                         break;
     433             :         }
     434          26 :         target[iCh] = '\0';
     435          26 : }
     436          26 : inline void strTrimRight(char* target) {
     437          26 :         return strTrimRight(target, " \t\r\n", 4);
     438             : }
     439             : 
     440             : #endif  // #ifdef SCID_MISC_H
     441             : 
     442             : //////////////////////////////////////////////////////////////////////
     443             : //  EOF: misc.h
     444             : //////////////////////////////////////////////////////////////////////
     445             : 

Generated by: LCOV version 1.13