LCOV - code coverage report
Current view: top level - asar - libstr.cpp (source / functions) Coverage Total Hit
Test: asar.info Lines: 84.0 % 257 216
Test Date: 2024-01-15 16:26:31 Functions: 100.0 % 21 21
Branches: 71.0 % 200 142

             Branch data     Line data    Source code
       1                 :             : #include "std-includes.h"
       2                 :             : #include "libstr.h"
       3                 :             : #include "virtualfile.h"
       4                 :             : #include "asar.h"
       5                 :             : #include "warnings.h"
       6                 :             : 
       7                 :             : #define typed_malloc(type, count) (type*)malloc(sizeof(type)*(count))
       8                 :             : #define typed_realloc(type, ptr, count) (type*)realloc(ptr, sizeof(type)*(count))
       9                 :             : 
      10                 :             : 
      11                 :             : // RPG Hacker: Functions below are copied over from Asar 2.0 branch for the sole purpose of generating
      12                 :             : // non-UTF-8 deprecation warnings in 1.9. Don't know if there's a better way to handle this, but it means
      13                 :             : // we should delete all of this again once we merge branches.
      14                 :             : 
      15                 :             : // vvvvvvvvvvvvvvvvvvvvvv
      16                 :             : 
      17                 :             : // Detects if str starts with a UTF-8 byte order mark.
      18                 :             : // If so, throws a warning, then returns the number of bytes we should skip ahead in the string.
      19                 :         300 : size_t check_bom(const char* str)
      20                 :             : {
      21                 :             :         // RPG Hacker: We could also check for BoMs of incompatible encodings here (like UTF-16)
      22                 :             :         // and throw errors, but not sure if that's worth adding. Asar never supported any wide
      23                 :             :         // encodings to begin with, so it's unreasonable to assume that any UTF-16 patches currently
      24                 :             :         // exist for it. As for future patches, those should be caught by the "must be UTF-8" checks
      25                 :             :         // I have already implemented further below.
      26                 :             :         // I think UTF-8 + BoM is the only case that could lead to confusion if we didn't handle it,
      27                 :             :         // so that's why I have added this.
      28   [ -  +  -  -  :         300 :         if (str[0u] == '\xEF' && str[1u] == '\xBB' && str[2u] == '\xBF')
                   -  - ]
      29                 :             :         {
      30                 :           0 :                 asar_throw_warning(0, warning_id_byte_order_mark_utf8);
      31                 :           0 :                 return 3u;
      32                 :             :         }
      33                 :             : 
      34                 :             :         return 0u;
      35                 :             : }
      36                 :             : 
      37                 :             : 
      38                 :       88855 : size_t utf8_val(int* codepoint, const char* inp) {
      39                 :       88855 :         unsigned char c = *inp++;
      40                 :             :         int val;
      41         [ +  - ]:       88855 :         if (c < 0x80) {
      42                 :             :                 // plain ascii
      43                 :       88855 :                 *codepoint = c;
      44                 :       88855 :                 return 1u;
      45                 :             :         }
      46                 :             :         // RPG Hacker: Byte sequences starting with 0xC0 or 0xC1 are invalid.
      47                 :             :         // So are byte sequences starting with anything >= 0xF5.
      48                 :             :         // And anything below 0xC0 indicates a follow-up byte and should never be at the start of a sequence.
      49         [ #  # ]:           0 :         else if (c > 0xC1 && c < 0xF5) {
      50                 :             :                 // 1, 2 or 3 continuation bytes
      51   [ #  #  #  # ]:           0 :                 int cont_byte_count = (c >= 0xF0) ? 3 : (c >= 0xE0) ? 2 : 1;
      52                 :             :                 // bit hack to extract the significant bits from the start byte
      53                 :           0 :                 val = (c & ((1 << (6 - cont_byte_count)) - 1));
      54         [ #  # ]:           0 :                 for (int i = 0; i < cont_byte_count; i++) {
      55                 :           0 :                         unsigned char next = *inp++;
      56         [ #  # ]:           0 :                         if ((next & 0xC0) != 0x80) {
      57                 :           0 :                                 *codepoint = -1;
      58                 :           0 :                                 return 0u;
      59                 :             :                         }
      60                 :           0 :                         val = (val << 6) | (next & 0x3F);
      61                 :             :                 }
      62                 :           0 :                 if (// too many cont.bytes
      63   [ #  #  #  # ]:           0 :                         (*inp & 0xC0) == 0x80 ||
      64                 :             : 
      65                 :             :                         // invalid codepoints
      66                 :           0 :                         val > 0x10FFFF ||
      67                 :             : 
      68                 :             :                         // check overlong encodings
      69         [ #  # ]:           0 :                         (cont_byte_count == 3 && val < 0x1000) ||
      70         [ #  # ]:           0 :                         (cont_byte_count == 2 && val < 0x800) ||
      71         [ #  # ]:           0 :                         (cont_byte_count == 1 && val < 0x80) ||
      72                 :             : 
      73                 :             :                         // UTF16 surrogates
      74         [ #  # ]:           0 :                         (val >= 0xD800 && val <= 0xDFFF)
      75                 :             :                         ) {
      76                 :           0 :                         *codepoint = -1;
      77                 :           0 :                         return 0u;
      78                 :             :                 };
      79                 :           0 :                 *codepoint = val;
      80                 :           0 :                 return 1u + cont_byte_count;
      81                 :             :         }
      82                 :             : 
      83                 :             :         // if none of the above, this couldn't possibly be a valid encoding
      84                 :           0 :         *codepoint = -1;
      85                 :           0 :         return 0u;
      86                 :             : }
      87                 :             : 
      88                 :         300 : bool is_valid_utf8(const char* inp) {
      89         [ +  + ]:       89155 :         while (*inp != '\0') {
      90                 :             :                 int codepoint;
      91                 :       88855 :                 inp += utf8_val(&codepoint, inp);
      92                 :             : 
      93         [ -  + ]:       88855 :                 if (codepoint == -1) return false;
      94                 :             :         }
      95                 :             : 
      96                 :             :         return true;
      97                 :             : }
      98                 :             : 
      99                 :             : // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     100                 :             : 
     101                 :             : 
     102                 :         110 : char * readfile(const char * fname, const char * basepath)
     103                 :             : {
     104                 :         110 :         virtual_file_handle myfile = filesystem->open_file(fname, basepath);
     105         [ +  - ]:         110 :         if (myfile == INVALID_VIRTUAL_FILE_HANDLE) return nullptr;
     106                 :         110 :         size_t datalen = filesystem->get_file_size(myfile);
     107                 :         110 :         char * data= typed_malloc(char, datalen+1);
     108                 :         110 :         data[filesystem->read_file(myfile, data, 0u, datalen)] = 0;
     109                 :         110 :         filesystem->close_file(myfile);
     110                 :             :         int inpos=0;
     111                 :             :         int outpos=0;
     112                 :         110 :         inpos += check_bom(data + inpos);
     113         [ +  + ]:       76900 :         while (data[inpos])
     114                 :             :         {
     115         [ +  - ]:       76790 :                 if (data[inpos]!='\r') data[outpos++]=data[inpos];
     116                 :       76790 :                 inpos++;
     117                 :             :         }
     118                 :         110 :         data[outpos]=0;
     119         [ -  + ]:         110 :         if (!is_valid_utf8(data)) asar_throw_warning(0, warning_id_feature_deprecated, "non-UTF-8 source files", "Re-save the file as UTF-8 in a text editor of choice and avoid using non-ASCII characters in Asar versions < 2.0");
     120                 :             :         return data;
     121                 :             : }
     122                 :             : 
     123                 :             : // RPG Hacker: like readfile(), but doesn't use virtual file system
     124                 :             : // and instead read our file directly.
     125                 :         190 : char * readfilenative(const char * fname)
     126                 :             : {
     127                 :         190 :         FILE* myfile = fopen(fname, "rb");
     128         [ +  - ]:         190 :         if (myfile == nullptr) return nullptr;
     129                 :         190 :         fseek(myfile, 0, SEEK_END);
     130                 :         190 :         size_t datalen = (size_t)ftell(myfile);
     131                 :         190 :         fseek(myfile, 0, SEEK_SET);
     132                 :         190 :         char * data = typed_malloc(char, datalen + 1);
     133                 :         190 :         data[fread(data, 1u, datalen, myfile)] = 0;
     134                 :         190 :         fclose(myfile);
     135                 :             :         int inpos = 0;
     136                 :             :         int outpos = 0;
     137                 :         190 :         inpos += check_bom(data + inpos);
     138         [ +  + ]:       12255 :         while (data[inpos])
     139                 :             :         {
     140         [ +  - ]:       12065 :                 if (data[inpos] != '\r') data[outpos++] = data[inpos];
     141                 :       12065 :                 inpos++;
     142                 :             :         }
     143                 :         190 :         data[outpos] = 0;
     144         [ -  + ]:         190 :         if (!is_valid_utf8(data)) asar_throw_warning(0, warning_id_feature_deprecated, "non-UTF-8 source files", "Re-save the file as UTF-8 in a text editor of choice and avoid using non-ASCII characters in Asar versions < 2.0");
     145                 :             :         return data;
     146                 :             : }
     147                 :             : 
     148                 :         111 : bool readfile(const char * fname, const char * basepath, char ** data, int * len)
     149                 :             : {
     150                 :         111 :         virtual_file_handle myfile = filesystem->open_file(fname, basepath);
     151         [ +  + ]:         111 :         if (!myfile) return false;
     152                 :         108 :         size_t datalen = filesystem->get_file_size(myfile);
     153                 :         108 :         *data= typed_malloc(char, datalen);
     154                 :         108 :         *len = (int)filesystem->read_file(myfile, *data, 0, datalen);
     155                 :         108 :         filesystem->close_file(myfile);
     156                 :         108 :         return true;
     157                 :             : }
     158                 :             : 
     159                 :             : #define dequote(var, next, error) if (var=='"') do { next; while (var!='"' && var != '\0') { if (!var) error; next; } if (var == '\0') error; next; } while(0); else if (var=='\'') do { next; if (!var) error; /* ''' special case hack */ if (var=='\'') { next; if (var!='\'') error; next; } else { next; while (var!='\'' && var != '\0') { if (!var) error; next; } if (var == '\0') error; next; } } while(0)
     160                 :             : #define skippar(var, next, error) dequote(var, next, error); else if (var=='(') { int par=1; next; while (par) { dequote(var, next, error); else { \
     161                 :             :                                 if (var=='(') par++; if (var==')') par--; if (!var) error; next; } } } else if (var==')') error
     162                 :             : 
     163                 :         484 : string& string::replace(const char * instr, const char * outstr, bool all)
     164                 :             : {
     165                 :             :         string& thisstring=*this;
     166         [ -  + ]:         484 :         if (!all)
     167                 :             :         {
     168                 :             :                 const char * ptr=strstr(thisstring, instr);
     169         [ #  # ]:           0 :                 if (!ptr) return thisstring;
     170                 :           0 :                 string out=STR substr(thisstring, (int)(ptr-thisstring.data()))+outstr+(ptr+strlen(instr));
     171                 :             :                 thisstring =out;
     172                 :             :                 return thisstring;
     173                 :           0 :         }
     174                 :             :         //performance hack (obviously for ", "->"," in asar, but who cares, it's a performance booster)
     175   [ +  +  -  + ]:         484 :         if (strlen(instr)==strlen(outstr)+1 && !memcmp(instr, outstr, strlen(outstr)))
     176                 :             :         {
     177                 :             :                 const char * indat= thisstring;
     178                 :         469 :                 char * trueoutdat= typed_malloc(char, strlen(indat)+1);
     179                 :             :                 char * outdat=trueoutdat;
     180                 :         469 :                 int thelen=(int)strlen(outstr);
     181                 :             :                 //nested hack
     182         [ +  + ]:         469 :                 if (thelen==0)
     183                 :             :                 {
     184                 :           1 :                         char thechar=instr[0];
     185         [ +  + ]:          31 :                         while (*indat)
     186                 :             :                         {
     187         [ +  + ]:          30 :                                 if (*indat==thechar) indat++;
     188                 :          27 :                                 else *outdat++=*indat++;
     189                 :             :                         }
     190                 :           1 :                         *outdat=0;
     191                 :             :                         thisstring =trueoutdat;
     192                 :           1 :                         free(trueoutdat);
     193                 :           1 :                         return thisstring;
     194                 :             :                 }
     195         [ +  - ]:         468 :                 else if (thelen==1)
     196                 :             :                 {
     197                 :         468 :                         char firstchar=instr[0];
     198                 :         468 :                         char secondchar=instr[1];
     199         [ +  + ]:        7025 :                         while (*indat)
     200                 :             :                         {
     201         [ +  + ]:        6557 :                                 if (*indat==firstchar)
     202                 :             :                                 {
     203                 :         527 :                                         *outdat++=*indat++;
     204         [ +  + ]:        1052 :                                         while (*indat==secondchar) indat++;
     205                 :             :                                 }
     206                 :        6030 :                                 else *outdat++=*indat++;
     207                 :             :                         }
     208                 :         468 :                         *outdat=0;
     209                 :             :                         thisstring =trueoutdat;
     210                 :         468 :                         free(trueoutdat);
     211                 :         468 :                         return thisstring;
     212                 :             :                 }
     213                 :             :                 else
     214                 :             :                 //end hack
     215                 :             :                 {
     216                 :           0 :                         char thehatedchar=instr[thelen];
     217         [ #  # ]:           0 :                         while (*indat)
     218                 :             :                         {
     219         [ #  # ]:           0 :                                 if (!memcmp(indat, outstr, (size_t)thelen))
     220                 :             :                                 {
     221                 :           0 :                                         memcpy(outdat, outstr, (size_t)thelen);
     222                 :           0 :                                         outdat+=thelen;
     223                 :           0 :                                         indat+=thelen;
     224         [ #  # ]:           0 :                                         while (*indat==thehatedchar) indat++;
     225                 :             :                                 }
     226                 :           0 :                                 else *outdat++=*indat++;
     227                 :             :                         }
     228                 :             :                 }
     229                 :           0 :                 *outdat=0;
     230                 :             :                 thisstring =trueoutdat;
     231                 :           0 :                 free(trueoutdat);
     232                 :           0 :                 return thisstring;
     233                 :             :         }
     234                 :             :         //end hack
     235                 :             :         bool replaced=true;
     236         [ +  + ]:          45 :         while (replaced)
     237                 :             :         {
     238                 :             :                 replaced=false;
     239                 :          30 :                 string out;
     240                 :             :                 const char * in= thisstring;
     241                 :          30 :                 int inlen=(int)strlen(instr);
     242         [ +  + ]:         537 :                 while (*in)
     243                 :             :                 {
     244         [ +  + ]:         507 :                         if (!strncmp(in, instr, (size_t)inlen))
     245                 :             :                         {
     246                 :             :                                 replaced=true;
     247                 :          15 :                                 out+=outstr;
     248                 :          15 :                                 in+=inlen;
     249                 :             :                         }
     250                 :         492 :                         else out+=*in++;
     251                 :             :                 }
     252                 :             :                 thisstring =out;
     253                 :          30 :         }
     254                 :             :         return thisstring;
     255                 :             : }
     256                 :             : 
     257                 :     2062214 : string& string::qreplace(const char * instr, const char * outstr, bool all)
     258                 :             : {
     259                 :             :         string& thisstring =*this;
     260         [ +  + ]:     2062214 :         if (!strstr(thisstring, instr)) return thisstring;
     261   [ +  +  -  + ]:         604 :         if (!strchr(thisstring, '"') && !strchr(thisstring, '\''))
     262                 :             :         {
     263                 :         484 :                 thisstring.replace(instr, outstr, all);
     264                 :         484 :                 return thisstring;
     265                 :             :         }
     266                 :             :         bool replaced=true;
     267         [ +  + ]:         345 :         while (replaced)
     268                 :             :         {
     269                 :             :                 replaced=false;
     270                 :         225 :                 string out;
     271         [ +  + ]:        5970 :                 for (int i=0;thisstring[i];)
     272                 :             :                 {
     273                 :       12087 :                         dequote(thisstring[i], out+= thisstring[i++], return thisstring);
     274                 :             :                         else
     275                 :             :                         {
     276         [ +  + ]:        5214 :                                 if (!strncmp((const char*)thisstring + i, instr, strlen(instr)))
     277                 :             :                                 {
     278                 :             :                                         replaced = true;
     279                 :         186 :                                         out += outstr;
     280                 :         186 :                                         i += (int)strlen(instr);
     281         [ -  + ]:         186 :                                         if (!all)
     282                 :             :                                         {
     283                 :           0 :                                                 out += ((const char*)thisstring) + i;
     284                 :             :                                                 thisstring = out;
     285                 :           0 :                                                 return thisstring;
     286                 :             :                                         }
     287                 :             :                                 }
     288                 :             :                                 // randomdude999: prevent appending the null terminator to the output
     289                 :        5028 :                                 else if (thisstring[i]) out += thisstring[i++];
     290                 :             :                         }
     291                 :             :                 }
     292                 :             :                 thisstring =out;
     293                 :         225 :         }
     294                 :             :         return thisstring;
     295                 :             : }
     296                 :             : 
     297                 :      440694 : bool confirmquotes(const char * str)
     298                 :             : {
     299         [ +  + ]:     3779634 :         for (int i=0;str[i];)
     300                 :             :         {
     301                 :     3352145 :                 dequote(str[i], i++, return false);
     302                 :     3337798 :                 else i++;
     303                 :             :         }
     304                 :             :         return true;
     305                 :             : }
     306                 :             : 
     307                 :      107211 : bool confirmqpar(const char * str)
     308                 :             : {
     309         [ +  + ]:      222679 :         for (int i=0;str[i];)
     310                 :             :         {
     311                 :      124307 :                 skippar(str[i], i++, return false);
     312                 :      114584 :                 else i++;
     313                 :             :         }
     314                 :             :         return true;
     315                 :             : }
     316                 :             : 
     317                 :      872273 : char ** nsplit(char * str, const char * key, int maxlen, int * len)
     318                 :             : {
     319         [ +  + ]:      872273 :         if (!strstr(str, key))
     320                 :             :         {
     321                 :      653199 :                 char ** out= typed_malloc(char*, 2);
     322                 :      653199 :                 out[0]=str;
     323                 :      653199 :                 out[1]=nullptr;
     324         [ +  + ]:      653199 :                 if (len) *len=1;
     325                 :      653199 :                 return out;
     326                 :             :         }
     327                 :      219074 :         int keylen=(int)strlen(key);
     328                 :             :         int count=7; //makes the default alloc 8 elements, sounds fair.
     329         [ -  + ]:      219074 :         if (maxlen && count>maxlen) count=maxlen;
     330                 :      219074 :         char ** outdata= typed_malloc(char*, (size_t)count+1);
     331                 :             :         
     332                 :             :         int newcount=0;
     333                 :             :         char *thisentry=str;
     334                 :      219074 :         outdata[newcount++]=thisentry;
     335         [ +  + ]:      654952 :         while((thisentry = strstr(thisentry, key))){
     336                 :      435878 :                 *thisentry = 0;
     337                 :      435878 :                 thisentry += keylen;
     338                 :      435878 :                 outdata[newcount++]=thisentry;
     339         [ +  + ]:      435878 :                 if(newcount >= count)
     340                 :             :                 {
     341                 :         276 :                         outdata = typed_realloc(char *, outdata, count * 2);
     342                 :             :                         count *= 2;
     343                 :             :                 }
     344                 :             :         }
     345                 :             :         
     346                 :      219074 :         outdata[newcount]= nullptr;
     347         [ +  + ]:      219074 :         if (len) *len=newcount;
     348                 :             :         return outdata;
     349                 :             : }
     350                 :             : 
     351                 :      873228 : char ** qnsplit(char * str, const char * key, int maxlen, int * len)
     352                 :             : {
     353   [ +  +  +  + ]:      873228 :         if (!strchr(str, '"') && !strchr(str, '\'')) return nsplit(str, key, maxlen, len);
     354                 :        1518 :         int keylen=(int)strlen(key);
     355                 :             :         int count=7;
     356         [ -  + ]:        1518 :         if (maxlen && count>maxlen) count=maxlen;
     357                 :        1518 :         char ** outdata= typed_malloc(char*, (size_t)count+1);
     358                 :             :         int newcount=0;
     359                 :             :         char * thisentry=str;
     360                 :        1518 :         outdata[newcount++]=thisentry;
     361         [ +  + ]:       19218 :         while (*thisentry) /*todo fix*/
     362                 :             :         {
     363                 :       38572 :                 dequote(*thisentry, thisentry++, return nullptr);
     364         [ +  + ]:       15864 :                 else if (!strncmp(thisentry, key, (size_t)keylen))
     365                 :             :                 {
     366                 :         858 :                         *thisentry=0;
     367                 :         858 :                         thisentry+=keylen;
     368                 :         858 :                         outdata[newcount++]=thisentry;
     369         [ -  + ]:         858 :                         if(newcount >= count)
     370                 :             :                         {
     371                 :           0 :                                 outdata = typed_realloc(char *, outdata, count * 2);
     372                 :             :                                 count *= 2;
     373                 :             :                         }
     374                 :             :                 }
     375                 :       15006 :                 else thisentry++;
     376                 :             :         }
     377                 :        1518 :         outdata[newcount]= nullptr;
     378         [ +  + ]:        1518 :         if (len) *len=newcount;
     379                 :             :         return outdata;
     380                 :             : }
     381                 :             : 
     382                 :      110033 : char ** qpnsplit(char * str, const char * key, int maxlen, int * len)
     383                 :             : {
     384                 :      110033 :         int keylen=(int)strlen(key);
     385                 :             :         int count=7;
     386         [ -  + ]:      110033 :         if (maxlen && count>maxlen) count=maxlen;
     387                 :      110033 :         char ** outdata= typed_malloc(char*, (size_t)count+1);
     388                 :             :         
     389                 :             :         int newcount=0;
     390                 :             :         char * thisentry=str;
     391                 :      110033 :         outdata[newcount++]=thisentry;
     392         [ +  + ]:      236478 :         while (*thisentry)
     393                 :             :         {
     394                 :      136738 :                 skippar(*thisentry, thisentry++, return nullptr);
     395         [ +  + ]:      125110 :                 else if (!strncmp(thisentry, key, (size_t)keylen))
     396                 :             :                 {
     397                 :        1748 :                         *thisentry=0;
     398                 :        1748 :                         thisentry+=keylen;
     399                 :        1748 :                         outdata[newcount++]=thisentry;
     400         [ +  + ]:        1748 :                         if(newcount >= count)
     401                 :             :                         {
     402                 :          21 :                                 outdata = typed_realloc(char *, outdata, count * 2);
     403                 :             :                                 count *= 2;
     404                 :             :                         }
     405                 :             :                 }
     406                 :      123362 :                 else thisentry++;
     407                 :             :         }
     408                 :      110033 :         outdata[newcount]= nullptr;
     409         [ +  + ]:      110033 :         if (len) *len=newcount;
     410                 :             :         return outdata;
     411                 :             : }
     412                 :             : 
     413                 :      438141 : string &strip_prefix(string &str, char c, bool multi)
     414                 :             : {
     415         [ +  + ]:      438141 :         if(!multi){
     416         [ +  + ]:        1149 :                 if(str.data()[0] == c){
     417                 :         579 :                         str = string(str.data() + 1, str.length() - 1);
     418                 :             :                 }
     419                 :        1149 :                 return str;
     420                 :             :         }
     421                 :             :         int length = str.length();
     422         [ +  + ]:      436992 :         for(int i = 0; i < length; i++){
     423         [ +  - ]:      326485 :                 if(str.data()[i] != c){
     424                 :      326485 :                         str = string(str.data() + i, str.length() - i);
     425                 :      326485 :                         return str;
     426                 :             :                 }
     427                 :             :         }
     428                 :             :         return str;
     429                 :             : }
     430                 :             : 
     431                 :      437055 : string &strip_suffix(string &str, char c, bool multi)
     432                 :             : {
     433         [ +  + ]:      437055 :         if(!multi){
     434         [ +  - ]:          63 :                 if(str.data()[str.length() - 1] == c){
     435                 :          63 :                         str.truncate(str.length() - 1);
     436                 :             :                 }
     437                 :          63 :                 return str;
     438                 :             :         }
     439         [ +  + ]:      437013 :         for(int i = str.length() - 1; i >= 0; i--){
     440         [ +  + ]:      326506 :                 if(str.data()[i] != c){
     441                 :      326485 :                         str.truncate(i + 1);
     442                 :      326485 :                         return str;
     443                 :             :                 }
     444                 :             :         }
     445                 :             :         return str;
     446                 :             : }
     447                 :             : 
     448                 :      436992 : string &strip_both(string &str, char c, bool multi)
     449                 :             : {
     450                 :      436992 :         return strip_suffix(strip_prefix(str, c, multi), c, multi);
     451                 :             : }
     452                 :             : 
     453                 :      543010 : string &strip_whitespace(string &str)
     454                 :             : {
     455         [ +  + ]:      543399 :         for(int i = str.length() - 1; i >= 0; i--){
     456   [ +  +  +  - ]:      538317 :                 if(str.data()[i] != ' ' && str.data()[i] != '\t'){
     457                 :      537928 :                         str.truncate(i + 1);
     458                 :             :                         break;
     459                 :             :                 }
     460                 :             :         }
     461                 :             :         
     462                 :             :         int length = str.length();
     463         [ +  + ]:      543295 :         for(int i = 0; i < length; i++){
     464   [ +  +  -  + ]:      538213 :                 if(str.data()[i] != ' ' && str.data()[i] != '\t'){
     465                 :      537928 :                         str = string(str.data() + i, str.length() - i);
     466                 :      537928 :                         return str;
     467                 :             :                 }
     468                 :             :         }
     469                 :             :         return str;
     470                 :             : }
     471                 :             : 
     472                 :        4506 : char * itrim(char * str, const char * left, const char * right, bool multi)
     473                 :             : {
     474                 :        4506 :         string tmp(str);
     475                 :        4506 :         return strcpy(str, itrim(tmp, left, right, multi).data());
     476                 :        4506 : }
     477                 :             : 
     478                 :             : //todo merge above with this
     479                 :        4929 : string &itrim(string &input, const char * left, const char * right, bool multi)
     480                 :             : {
     481                 :             :         bool nukeright=true;
     482                 :             :         int totallen=input.length();
     483                 :        4929 :         int rightlen=(int)strlen(right);
     484         [ +  + ]:        4929 :         if (rightlen && rightlen<=totallen)
     485                 :             :         {
     486                 :             :                 do
     487                 :             :                 {
     488                 :       10919 :                         const char * rightend=right+rightlen;
     489                 :       10919 :                         const char * strend=input.data()+totallen;
     490         [ +  + ]:       22411 :                         while (right!=rightend)
     491                 :             :                         {
     492                 :       11492 :                                 rightend--;
     493                 :       11492 :                                 strend--;
     494         [ +  + ]:       11492 :                                 if (to_lower(*strend)!=to_lower(*rightend)) nukeright=false;
     495                 :             :                         }
     496         [ +  + ]:       10919 :                         if (nukeright)
     497                 :             :                         {
     498                 :        8024 :                                 totallen-=rightlen;
     499                 :             :                                 input.truncate(totallen);
     500                 :             :                         }
     501   [ +  +  +  + ]:       10919 :                 } while (multi && nukeright && rightlen<=totallen);
     502                 :             :         }
     503                 :             :         bool nukeleft=true;
     504                 :        4929 :         int leftlen = strlen(left);
     505   [ +  +  +  - ]:        4929 :         if(!multi && leftlen == 1 && input.data()[0] == left[0])
     506                 :             :         {
     507                 :         102 :                 return input = string(input.data()+1, (input.length()-1));
     508                 :             :         }
     509                 :             :         else
     510                 :             :         {
     511                 :             :                 do
     512                 :             :                 {
     513                 :             :                         
     514         [ +  + ]:       10847 :                         for (int i = 0; i < leftlen; i++)
     515                 :             :                         {
     516         [ +  + ]:        5263 :                                 if (to_lower(input.data()[i])!=to_lower(left[i])) nukeleft=false;
     517                 :             :                         }
     518         [ +  + ]:        6662 :                         if (nukeleft) input = string(input.data()+leftlen, (input.length()-leftlen));
     519         [ +  + ]:        5584 :                 } while (multi && nukeleft);
     520                 :             :         }
     521                 :             :         return input;
     522                 :             : }
     523                 :             : 
     524                 :           3 : char* strqpchr(const char* str, char key)
     525                 :             : {
     526         [ +  - ]:          12 :         while (*str)
     527                 :             :         {
     528                 :          36 :                 skippar(*str, str++, return nullptr);
     529         [ +  + ]:           6 :                 else if (*str == key) return const_cast<char*>(str);
     530                 :             :                 else if (!*str) return nullptr;
     531                 :           3 :                 else str++;
     532                 :             :         }
     533                 :             :         return nullptr;
     534                 :             : }
     535                 :             : 
     536                 :             : 
     537                 :          81 : char* strqpstr(const char* str, const char* key)
     538                 :             : {
     539                 :          81 :         size_t keylen = strlen(key);
     540         [ +  + ]:         411 :         while (*str)
     541                 :             :         {
     542                 :         450 :                 skippar(*str, str++, return nullptr);
     543         [ +  + ]:         399 :                 else if (!strncmp(str, key, keylen)) return const_cast<char*>(str);
     544                 :             :                 else if (!*str) return nullptr;
     545                 :         321 :                 else str++;
     546                 :             :         }
     547                 :             :         return nullptr;
     548                 :             : }
     549                 :             : 
     550                 :             : extern const uint8_t char_props[256] = {
     551                 :             :         //x0   x1   x2   x3   x4   x5   x6   x7   x8   x9   xA   xB   xC   xD   xE   xF
     552                 :             :         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x00,0x00, // 0x
     553                 :             :         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1x
     554                 :             :         0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2x  !"#$%&'()*+,-./
     555                 :             :         0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00, // 3x 0123456789:;<=>?
     556                 :             :         0x00,0x23,0x23,0x23,0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, // 4x @ABCDEFGHIJKLMNO
     557                 :             :         0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x00,0x00,0x00,0x00,0x08, // 5x PQRSTUVWXYZ[\]^_
     558                 :             :         0x00,0x25,0x25,0x25,0x25,0x25,0x25,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, // 6x `abcdefghijklmno
     559                 :             :         0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00, // 7x pqrstuvwxyz{|}~
     560                 :             :         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8x
     561                 :             :         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9x
     562                 :             :         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Ax
     563                 :             :         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Bx
     564                 :             :         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Cx
     565                 :             :         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Dx
     566                 :             :         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Ex
     567                 :             :         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Fx
     568                 :             : };
        

Generated by: LCOV version 2.0-1