#include "rar.hpp" const char *NullToEmpty(const char *Str) { return Str==NULL ? "":Str; } const wchar *NullToEmpty(const wchar *Str) { return Str==NULL ? L"":Str; } void IntToExt(const char *Src,char *Dest,size_t DestSize) { #ifdef _WIN_ALL OemToCharBuffA(Src,Dest,(DWORD)DestSize); Dest[DestSize-1]=0; #elif defined(_ANDROID) wchar DestW[NM]; JniCharToWide(Src,DestW,ASIZE(DestW),true); WideToChar(DestW,Dest,DestSize); #else if (Dest!=Src) strncpyz(Dest,Src,DestSize); #endif } int stricomp(const char *s1,const char *s2) { #ifdef _WIN_ALL return CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE|SORT_STRINGSORT,s1,-1,s2,-1)-2; #else while (toupper(*s1)==toupper(*s2)) { if (*s1==0) return 0; s1++; s2++; } return s1 < s2 ? -1 : 1; #endif } int strnicomp(const char *s1,const char *s2,size_t n) { #ifdef _WIN_ALL // If we specify 'n' exceeding the actual string length, CompareString goes // beyond the trailing zero and compares garbage. So we need to limit 'n' // to real string length. // It is important to use strnlen (or memchr(...,0)) instead of strlen, // because data can be not zero terminated. size_t l1=Min(strnlen(s1,n),n); size_t l2=Min(strnlen(s2,n),n); return CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE|SORT_STRINGSORT,s1,(int)l1,s2,(int)l2)-2; #else if (n==0) return 0; while (toupper(*s1)==toupper(*s2)) { if (*s1==0 || --n==0) return 0; s1++; s2++; } return s1 < s2 ? -1 : 1; #endif } wchar* RemoveEOL(wchar *Str) { for (int I=(int)wcslen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n' || Str[I]==' ' || Str[I]=='\t');I--) Str[I]=0; return Str; } wchar* RemoveLF(wchar *Str) { for (int I=(int)wcslen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--) Str[I]=0; return(Str); } unsigned char loctolower(unsigned char ch) { #ifdef _WIN_ALL // Convert to LPARAM first to avoid a warning in 64 bit mode. return((int)(LPARAM)CharLowerA((LPSTR)ch)); #else return(tolower(ch)); #endif } unsigned char loctoupper(unsigned char ch) { #ifdef _WIN_ALL // Convert to LPARAM first to avoid a warning in 64 bit mode. return((int)(LPARAM)CharUpperA((LPSTR)ch)); #else return(toupper(ch)); #endif } // toupper with English only results if English input is provided. // It avoids Turkish (small i) -> (big I with dot) conversion problem. // We do not define 'ch' as 'int' to avoid necessity to cast all // signed chars passed to this function to unsigned char. unsigned char etoupper(unsigned char ch) { if (ch=='i') return('I'); return(toupper(ch)); } // Unicode version of etoupper. wchar etoupperw(wchar ch) { if (ch=='i') return('I'); return(toupperw(ch)); } // We do not want to cast every signed char to unsigned when passing to // isdigit, so we implement the replacement. Shall work for Unicode too. // If chars are signed, conversion from char to int could generate negative // values, resulting in undefined behavior in standard isdigit. bool IsDigit(int ch) { return(ch>='0' && ch<='9'); } // We do not want to cast every signed char to unsigned when passing to // isspace, so we implement the replacement. Shall work for Unicode too. // If chars are signed, conversion from char to int could generate negative // values, resulting in undefined behavior in standard isspace. bool IsSpace(int ch) { return(ch==' ' || ch=='\t'); } // We do not want to cast every signed char to unsigned when passing to // isalpha, so we implement the replacement. Shall work for Unicode too. // If chars are signed, conversion from char to int could generate negative // values, resulting in undefined behavior in standard function. bool IsAlpha(int ch) { return(ch>='A' && ch<='Z' || ch>='a' && ch<='z'); } void BinToHex(const byte *Bin,size_t BinSize,char *HexA,wchar *HexW,size_t HexSize) { uint A=0,W=0; // ASCII and Unicode hex output positions. for (uint I=0;I> 4; uint Low=Bin[I] & 0xf; uint HighHex=High>9 ? 'a'+High-10:'0'+High; uint LowHex=Low>9 ? 'a'+Low-10:'0'+Low; if (HexA!=NULL && A0) HexA[A]=0; if (HexW!=NULL && HexSize>0) HexW[W]=0; } #ifndef SFX_MODULE uint GetDigits(uint Number) { uint Digits=1; while (Number>=10) { Number/=10; Digits++; } return Digits; } #endif bool LowAscii(const char *Str) { for (int I=0;Str[I]!=0;I++) if ((byte)Str[I]<32 || (byte)Str[I]>127) return false; return true; } bool LowAscii(const wchar *Str) { for (int I=0;Str[I]!=0;I++) { // We convert wchar_t to uint just in case if some compiler // uses signed wchar_t. if ((uint)Str[I]<32 || (uint)Str[I]>127) return false; } return true; } int wcsicompc(const wchar *Str1,const wchar *Str2) { #if defined(_UNIX) return wcscmp(Str1,Str2); #else return wcsicomp(Str1,Str2); #endif } // safe strncpy: copies maxlen-1 max and always returns zero terminated dest char* strncpyz(char *dest, const char *src, size_t maxlen) { if (maxlen>0) { strncpy(dest,src,maxlen-1); dest[maxlen-1]=0; } return dest; } // Safe wcsncpy: copies maxlen-1 max and always returns zero terminated dest. wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen) { if (maxlen>0) { wcsncpy(dest,src,maxlen-1); dest[maxlen-1]=0; } return dest; } // Safe strncat: resulting dest length cannot exceed maxlen and dest // is always zero terminated. Note that 'maxlen' parameter defines the entire // dest buffer size and is not compatible with standard strncat. char* strncatz(char* dest, const char* src, size_t maxlen) { size_t Length = strlen(dest); int avail=int(maxlen - Length - 1); if (avail > 0) strncat(dest, src, avail); return dest; } // Safe wcsncat: resulting dest length cannot exceed maxlen and dest // is always zero terminated. Note that 'maxlen' parameter defines the entire // dest buffer size and is not compatible with standard wcsncat. wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen) { size_t Length = wcslen(dest); int avail=int(maxlen - Length - 1); if (avail > 0) wcsncat(dest, src, avail); return dest; } void itoa(int64 n,char *Str) { char NumStr[50]; size_t Pos=0; do { NumStr[Pos++]=char(n%10)+'0'; n=n/10; } while (n!=0); for (size_t I=0;I= ASIZE(StrTable)) StrNum=0; wchar *Str=StrTable[StrNum]; CharToWide(Src,Str,MaxLength); Str[MaxLength-1]=0; return Str; } // Parse string containing parameters separated with spaces. // Support quote marks. Param can be NULL to return the pointer to next // parameter, which can be used to estimate the buffer size for Param. const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize) { while (IsSpace(*CmdLine)) CmdLine++; if (*CmdLine==0) return NULL; size_t ParamSize=0; bool Quote=false; while (*CmdLine!=0 && (Quote || !IsSpace(*CmdLine))) { if (*CmdLine=='\"') { if (CmdLine[1]=='\"') { // Insert the quote character instead of two adjoining quote characters. if (Param!=NULL && ParamSize