123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- #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
- // OemToCharBuff does not stop at 0, so let's check source length.
- size_t SrcLength=strlen(Src)+1;
- if (DestSize>SrcLength)
- DestSize=SrcLength;
- OemToCharBuffA(Src,Dest,(DWORD)DestSize);
- Dest[DestSize-1]=0;
- #else
- if (Dest!=Src)
- strncpyz(Dest,Src,DestSize);
- #endif
- }
- // Convert archived names and comments to Unicode.
- // Allows user to select a code page in GUI.
- void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Encoding)
- {
- #if defined(_WIN_ALL) // Console Windows RAR.
- if (Encoding==ACTW_UTF8)
- UtfToWide(Src,Dest,DestSize);
- else
- {
- Array<char> NameA;
- if (Encoding==ACTW_OEM)
- {
- NameA.Alloc(DestSize+1);
- IntToExt(Src,&NameA[0],NameA.Size());
- Src=&NameA[0];
- }
- CharToWide(Src,Dest,DestSize);
- }
- #else // RAR for Unix.
- if (Encoding==ACTW_UTF8)
- UtfToWide(Src,Dest,DestSize);
- else
- CharToWide(Src,Dest,DestSize);
- #endif
- // Ensure that we return a zero terminate string for security reason.
- // While [Jni]CharToWide might already do it, be protected in case of future
- // changes in these functions.
- if (DestSize>0)
- Dest[DestSize-1]=0;
- }
- 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;
- }
- #if defined(SFX_MODULE)
- // char version of etoupperw. Used in console SFX module only.
- // Fast toupper for English only input and output. Additionally to speed,
- // it also avoids Turkish small i to big I with dot conversion problem.
- // We do not define 'c' as 'int' to avoid necessity to cast all
- // signed chars passed to this function to unsigned char.
- unsigned char etoupper(unsigned char c)
- {
- return c>='a' && c<='z' ? c-'a'+'A' : c;
- }
- #endif
- // Fast toupper for English only input and output. Additionally to speed,
- // it also avoids Turkish small i to big I with dot conversion problem.
- // We do not define 'c' as 'int' to avoid necessity to cast all
- // signed wchars passed to this function to unsigned char.
- wchar etoupperw(wchar c)
- {
- return c>='a' && c<='z' ? c-'a'+'A' : c;
- }
- // 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<BinSize;I++)
- {
- uint High=Bin[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 && A<HexSize-2) // Need space for 2 chars and final zero.
- {
- HexA[A++]=(char)HighHex;
- HexA[A++]=(char)LowHex;
- }
- if (HexW!=NULL && W<HexSize-2) // Need space for 2 chars and final zero.
- {
- HexW[W++]=HighHex;
- HexW[W++]=LowHex;
- }
- }
- if (HexA!=NULL && HexSize>0)
- 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 (size_t 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 (size_t 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 *s1,const wchar *s2) // For path comparison.
- {
- #if defined(_UNIX)
- return wcscmp(s1,s2);
- #else
- return wcsicomp(s1,s2);
- #endif
- }
- int wcsnicompc(const wchar *s1,const wchar *s2,size_t n)
- {
- #if defined(_UNIX)
- return wcsncmp(s1,s2,n);
- #else
- return wcsnicomp(s1,s2,n);
- #endif
- }
- // Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest.
- void strncpyz(char *dest, const char *src, size_t maxlen)
- {
- if (maxlen>0)
- {
- while (--maxlen>0 && *src!=0)
- *dest++=*src++;
- *dest=0;
- }
- }
- // Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest.
- void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
- {
- if (maxlen>0)
- {
- while (--maxlen>0 && *src!=0)
- *dest++=*src++;
- *dest=0;
- }
- }
- // Safe append: resulting dest length cannot exceed maxlen and dest
- // is always zero terminated. 'maxlen' parameter defines the entire
- // dest buffer size and is not compatible with wcsncat.
- void strncatz(char* dest, const char* src, size_t maxlen)
- {
- size_t length = strlen(dest);
- if (maxlen > length)
- strncpyz(dest + length, src, maxlen - length);
- }
- // Safe append: resulting dest length cannot exceed maxlen and dest
- // is always zero terminated. 'maxlen' parameter defines the entire
- // dest buffer size and is not compatible with wcsncat.
- void wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
- {
- size_t length = wcslen(dest);
- if (maxlen > length)
- wcsncpyz(dest + length, src, maxlen - length);
- }
- void itoa(int64 n,char *Str,size_t MaxSize)
- {
- char NumStr[50];
- size_t Pos=0;
- int Neg=n < 0 ? 1 : 0;
- if (Neg)
- n=-n;
- do
- {
- if (Pos+1>=MaxSize-Neg)
- break;
- NumStr[Pos++]=char(n%10)+'0';
- n=n/10;
- } while (n!=0);
- if (Neg)
- NumStr[Pos++]='-';
- for (size_t I=0;I<Pos;I++)
- Str[I]=NumStr[Pos-I-1];
- Str[Pos]=0;
- }
- void itoa(int64 n,wchar *Str,size_t MaxSize)
- {
- wchar NumStr[50];
- size_t Pos=0;
- int Neg=n < 0 ? 1 : 0;
- if (Neg)
- n=-n;
- do
- {
- if (Pos+1>=MaxSize-Neg)
- break;
- NumStr[Pos++]=wchar(n%10)+'0';
- n=n/10;
- } while (n!=0);
- if (Neg)
- NumStr[Pos++]='-';
- for (size_t I=0;I<Pos;I++)
- Str[I]=NumStr[Pos-I-1];
- Str[Pos]=0;
- }
- const wchar* GetWide(const char *Src)
- {
- const size_t MaxLength=NM;
- static wchar StrTable[4][MaxLength];
- static uint StrNum=0;
- if (++StrNum >= 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<MaxSize-1)
- Param[ParamSize++]='\"';
- CmdLine++;
- }
- else
- Quote=!Quote;
- }
- else
- if (Param!=NULL && ParamSize<MaxSize-1)
- Param[ParamSize++]=*CmdLine;
- CmdLine++;
- }
- if (Param!=NULL)
- Param[ParamSize]=0;
- return CmdLine;
- }
- #ifndef RARDLL
- // For compatibility with existing translations we use %s to print Unicode
- // strings in format strings and convert them to %ls here. %s could work
- // without such conversion in Windows, but not in Unix wprintf.
- void PrintfPrepareFmt(const wchar *Org,wchar *Cvt,size_t MaxSize)
- {
- uint Src=0,Dest=0;
- while (Org[Src]!=0 && Dest<MaxSize-1)
- {
- if (Org[Src]=='%' && (Src==0 || Org[Src-1]!='%'))
- {
- uint SPos=Src+1;
- // Skipping a possible width specifier like %-50s.
- while (IsDigit(Org[SPos]) || Org[SPos]=='-')
- SPos++;
- if (Org[SPos]=='s' && Dest<MaxSize-(SPos-Src+1))
- {
- while (Src<SPos)
- Cvt[Dest++]=Org[Src++];
- Cvt[Dest++]='l';
- }
- }
- #ifdef _WIN_ALL
- // Convert \n to \r\n in Windows. Important when writing to log,
- // so other tools like Notebook can view resulting log properly.
- if (Org[Src]=='\n' && (Src==0 || Org[Src-1]!='\r'))
- Cvt[Dest++]='\r';
- #endif
- Cvt[Dest++]=Org[Src++];
- }
- Cvt[Dest]=0;
- }
- #endif
|