--- parser3/src/main/pa_string.C 2023/12/13 20:07:11 1.271 +++ parser3/src/main/pa_string.C 2026/01/06 13:07:58 1.284 @@ -1,7 +1,7 @@ /** @file Parser: string class. @see untalength_t.C. - Copyright (c) 2001-2023 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2001-2024 Art. Lebedev Studio (http://www.artlebedev.com) Authors: Konstantin Morshnev , Alexandr Petrosian */ @@ -12,171 +12,13 @@ #include "pa_charset.h" #include "pa_vregex.h" -volatile const char * IDENT_PA_STRING_C="$Id: pa_string.C,v 1.271 2023/12/13 20:07:11 moko Exp $" IDENT_PA_STRING_H; +volatile const char * IDENT_PA_STRING_C="$Id: pa_string.C,v 1.284 2026/01/06 13:07:58 moko Exp $" IDENT_PA_STRING_H; const String String::Empty; #define COMPILE_ASSERT(x) extern int assert_checker[(x) ? 1 : -1] COMPILE_ASSERT(sizeof(String::Languages) == sizeof(CORD)); -// pa_atoui is based on Manuel Novoa III _strto_l for uClibc - -template inline T pa_ato_any(const char *str, int base, const String* problem_source,const T max){ - T result = 0; - const char *pos = str; - - while (isspace(*pos)) /* skip leading whitespace */ - ++pos; - - if (base == 16 && *pos == '0') { /* handle option prefix */ - ++pos; - if (*pos == 'x' || *pos == 'X') { - ++pos; - } - } - - if (base == 0) { /* dynamic base */ - base = 10; /* default is 10 */ - if (*pos == '0') { - ++pos; - if (*pos == 'x' || *pos == 'X'){ - ++pos; - base=16; - } - } - } - - if (base < 2 || base > 16) { /* illegal base */ - throw Exception(PARSER_RUNTIME, 0, "base to must be an integer from 2 to 16"); - } - - T cutoff = max / base; - int cutoff_digit = (int)(max - cutoff * base); - - while(true) { - int digit; - - if ((*pos >= '0') && (*pos <= '9')) { - digit = (*pos - '0'); - } else if (*pos >= 'a') { - digit = (*pos - 'a' + 10); - } else if (*pos >= 'A') { - digit = (*pos - 'A' + 10); - } else break; - - if (digit >= base) { - break; - } - - ++pos; - - /* adjust number, with overflow check */ - if ((result > cutoff) || ((result == cutoff) && (digit > cutoff_digit))) { - throw Exception("number.format", problem_source, problem_source ? "out of range (int)" : "'%s' is out of range (int)", str); - } else { - result = result * base + digit; - } - } - - while(char c=*pos++) - if(!isspace(c)) - throw Exception("number.format", problem_source, problem_source ? "invalid number (int)" : "'%s' is invalid number (int)", str); - - return result; -} - -unsigned int pa_atoui(const char *str, int base, const String* problem_source){ - if(!str) - return 0; - - return pa_ato_any(str, base, problem_source, UINT_MAX); -} - -uint64_t pa_atoul(const char *str, int base, const String* problem_source){ - if(!str) - return 0; - - return pa_ato_any(str, base, problem_source, ULLONG_MAX); -} - -int pa_atoi(const char* str, int base, const String* problem_source) { - if(!str) - return 0; - - while(isspace(*str)) - str++; - - if(!*str) - return 0; - - const char *str_copy=str; - bool negative=false; - if(str[0]=='-') { - negative=true; - str++; - if(!*str || isspace(*str)) - throw Exception("number.format", problem_source, problem_source ? "invalid number (int)" : "'%s' is invalid number (int)", str_copy); - } else if(str[0]=='+') { - str++; - if(!*str || isspace(*str)) - throw Exception("number.format", problem_source, problem_source ? "invalid number (int)" : "'%s' is invalid number (int)", str_copy); - } - - unsigned int result=pa_atoui(str, base, problem_source); - - if(negative && result <= ((unsigned int)(-(1+INT_MIN)))+1) - return -(int)result; - - if(result<=INT_MAX) - return (int)result; - - throw Exception("number.format", problem_source, problem_source ? "out of range (int)" : "'%s' is out of range (int)", str_copy); -} - -double pa_atod(const char* str, const String* problem_source /* never null */) { - if(!str) - return 0; - - while(isspace(*str)) - str++; - - if(!*str) - return 0; - - bool negative=false; - if(str[0]=='-') { - negative=true; - str++; - if(!*str || isspace(*str)) - throw Exception("number.format", problem_source, "invalid number (double)"); - } else if(str[0]=='+') { - str++; - if(!*str || isspace(*str)) - throw Exception("number.format", problem_source, "invalid number (double)"); - } - - double result; - if(str[0]=='0') { - if(str[1]=='x' || str[1]=='X') { - // 0xABC - result=(double)pa_atoul(str, 0, problem_source); - return negative ? -result : result; - } else { - // skip leading 0000, to disable octal interpretation - do str++; while(*str=='0'); - } - } - - char *error_pos; - result=strtod(str, &error_pos); - - while(const char c=*error_pos++) - if(!isspace(c)) - throw Exception("number.format", problem_source, "invalid number (double)"); - - return negative ? -result : result; -} - // cord lib extension #ifndef DOXYGEN @@ -188,7 +30,7 @@ typedef struct { static int CORD_range_contains_chr_greater_then_proc(char c, size_t size, void* client_data) { - register chr_data * d = (chr_data *)client_data; + chr_data * d = (chr_data *)client_data; if (d -> countdown<=0) return(2); d -> countdown -= size; @@ -232,19 +74,27 @@ public: *this+=new String("match"); *this+=new String("postmatch"); for(int i=0; i=start', that's(<) impossible - return 0; // all chars are empty, just return empty string + return String::Body(); // all chars are empty, just return empty string } else - break; + break; CORD_prev(pos); } @@ -321,7 +171,7 @@ String::Body String::Body::trim(String:: if(found){ start+=char_length; if(start==our_length) - return 0; // all chars are empty, just return empty string + return String::Body(); // all chars are empty, just return empty string } else break; } @@ -345,7 +195,7 @@ String::Body String::Body::trim(String:: if(found){ end-=char_length; if(end==0) - return 0; // all chars are empty, just return empty string + return String::Body(); // all chars are empty, just return empty string } else break; } @@ -622,7 +472,7 @@ void String::split(ArrayString& result, if(size_t delim_length=strlen(delim)) { size_t pos_before; // while we have 'delim'... - while((pos_before=pos(delim, pos_after, lang))!=STRING_NOT_FOUND) { + while((pos_before=pos(String::Body(delim), pos_after, lang)) != STRING_NOT_FOUND) { result+=&mid(pos_after, pos_before); pos_after=pos_before+delim_length; } @@ -665,7 +515,7 @@ Table* String::match(VRegex* vregex, Row int ovector[ovector_size]; Table::Action_options table_options; - Table& table=*new Table(string_match_table_template, table_options); + Table& table=*new Table(string_match_table_template(), table_options); int prestart=0; int poststart=0; @@ -705,7 +555,7 @@ Table* String::match(VRegex* vregex, Row matches_count++; row_action(table, row, prestart - !action_was_executed, prefinish, poststart, postfinish, info); - if(!global || poststart>=subject_length) // last step, avoid prestart++ after last char + if(!global || (size_t)poststart>=subject_length) // last step, avoid prestart++ after last char break; prestart=poststart; @@ -768,7 +618,7 @@ String& String::change_case(Charset& sou } } result.langs=langs; - result.body=new_cstr; + result.body=String::Body(new_cstr); return result; }