1
0

strfn.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. #include "rar.hpp"
  2. const char *NullToEmpty(const char *Str)
  3. {
  4. return Str==NULL ? "":Str;
  5. }
  6. const wchar *NullToEmpty(const wchar *Str)
  7. {
  8. return Str==NULL ? L"":Str;
  9. }
  10. void IntToExt(const char *Src,char *Dest,size_t DestSize)
  11. {
  12. #ifdef _WIN_ALL
  13. // OemToCharBuff does not stop at 0, so let's check source length.
  14. size_t SrcLength=strlen(Src)+1;
  15. if (DestSize>SrcLength)
  16. DestSize=SrcLength;
  17. OemToCharBuffA(Src,Dest,(DWORD)DestSize);
  18. Dest[DestSize-1]=0;
  19. #else
  20. if (Dest!=Src)
  21. strncpyz(Dest,Src,DestSize);
  22. #endif
  23. }
  24. // Convert archived names and comments to Unicode.
  25. // Allows user to select a code page in GUI.
  26. void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Encoding)
  27. {
  28. #if defined(_WIN_ALL) // Console Windows RAR.
  29. if (Encoding==ACTW_UTF8)
  30. UtfToWide(Src,Dest,DestSize);
  31. else
  32. {
  33. Array<char> NameA;
  34. if (Encoding==ACTW_OEM)
  35. {
  36. NameA.Alloc(DestSize+1);
  37. IntToExt(Src,&NameA[0],NameA.Size());
  38. Src=&NameA[0];
  39. }
  40. CharToWide(Src,Dest,DestSize);
  41. }
  42. #else // RAR for Unix.
  43. if (Encoding==ACTW_UTF8)
  44. UtfToWide(Src,Dest,DestSize);
  45. else
  46. CharToWide(Src,Dest,DestSize);
  47. #endif
  48. // Ensure that we return a zero terminate string for security reason.
  49. // While [Jni]CharToWide might already do it, be protected in case of future
  50. // changes in these functions.
  51. if (DestSize>0)
  52. Dest[DestSize-1]=0;
  53. }
  54. int stricomp(const char *s1,const char *s2)
  55. {
  56. #ifdef _WIN_ALL
  57. return CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE|SORT_STRINGSORT,s1,-1,s2,-1)-2;
  58. #else
  59. while (toupper(*s1)==toupper(*s2))
  60. {
  61. if (*s1==0)
  62. return 0;
  63. s1++;
  64. s2++;
  65. }
  66. return s1 < s2 ? -1 : 1;
  67. #endif
  68. }
  69. int strnicomp(const char *s1,const char *s2,size_t n)
  70. {
  71. #ifdef _WIN_ALL
  72. // If we specify 'n' exceeding the actual string length, CompareString goes
  73. // beyond the trailing zero and compares garbage. So we need to limit 'n'
  74. // to real string length.
  75. // It is important to use strnlen (or memchr(...,0)) instead of strlen,
  76. // because data can be not zero terminated.
  77. size_t l1=Min(strnlen(s1,n),n);
  78. size_t l2=Min(strnlen(s2,n),n);
  79. return CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE|SORT_STRINGSORT,s1,(int)l1,s2,(int)l2)-2;
  80. #else
  81. if (n==0)
  82. return 0;
  83. while (toupper(*s1)==toupper(*s2))
  84. {
  85. if (*s1==0 || --n==0)
  86. return 0;
  87. s1++;
  88. s2++;
  89. }
  90. return s1 < s2 ? -1 : 1;
  91. #endif
  92. }
  93. wchar* RemoveEOL(wchar *Str)
  94. {
  95. for (int I=(int)wcslen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n' || Str[I]==' ' || Str[I]=='\t');I--)
  96. Str[I]=0;
  97. return Str;
  98. }
  99. wchar* RemoveLF(wchar *Str)
  100. {
  101. for (int I=(int)wcslen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--)
  102. Str[I]=0;
  103. return Str;
  104. }
  105. #if defined(SFX_MODULE)
  106. // char version of etoupperw. Used in console SFX module only.
  107. // Fast toupper for English only input and output. Additionally to speed,
  108. // it also avoids Turkish small i to big I with dot conversion problem.
  109. // We do not define 'c' as 'int' to avoid necessity to cast all
  110. // signed chars passed to this function to unsigned char.
  111. unsigned char etoupper(unsigned char c)
  112. {
  113. return c>='a' && c<='z' ? c-'a'+'A' : c;
  114. }
  115. #endif
  116. // Fast toupper for English only input and output. Additionally to speed,
  117. // it also avoids Turkish small i to big I with dot conversion problem.
  118. // We do not define 'c' as 'int' to avoid necessity to cast all
  119. // signed wchars passed to this function to unsigned char.
  120. wchar etoupperw(wchar c)
  121. {
  122. return c>='a' && c<='z' ? c-'a'+'A' : c;
  123. }
  124. // We do not want to cast every signed char to unsigned when passing to
  125. // isdigit, so we implement the replacement. Shall work for Unicode too.
  126. // If chars are signed, conversion from char to int could generate negative
  127. // values, resulting in undefined behavior in standard isdigit.
  128. bool IsDigit(int ch)
  129. {
  130. return ch>='0' && ch<='9';
  131. }
  132. // We do not want to cast every signed char to unsigned when passing to
  133. // isspace, so we implement the replacement. Shall work for Unicode too.
  134. // If chars are signed, conversion from char to int could generate negative
  135. // values, resulting in undefined behavior in standard isspace.
  136. bool IsSpace(int ch)
  137. {
  138. return ch==' ' || ch=='\t';
  139. }
  140. // We do not want to cast every signed char to unsigned when passing to
  141. // isalpha, so we implement the replacement. Shall work for Unicode too.
  142. // If chars are signed, conversion from char to int could generate negative
  143. // values, resulting in undefined behavior in standard function.
  144. bool IsAlpha(int ch)
  145. {
  146. return ch>='A' && ch<='Z' || ch>='a' && ch<='z';
  147. }
  148. void BinToHex(const byte *Bin,size_t BinSize,char *HexA,wchar *HexW,size_t HexSize)
  149. {
  150. uint A=0,W=0; // ASCII and Unicode hex output positions.
  151. for (uint I=0;I<BinSize;I++)
  152. {
  153. uint High=Bin[I] >> 4;
  154. uint Low=Bin[I] & 0xf;
  155. uint HighHex=High>9 ? 'a'+High-10:'0'+High;
  156. uint LowHex=Low>9 ? 'a'+Low-10:'0'+Low;
  157. if (HexA!=NULL && A<HexSize-2) // Need space for 2 chars and final zero.
  158. {
  159. HexA[A++]=(char)HighHex;
  160. HexA[A++]=(char)LowHex;
  161. }
  162. if (HexW!=NULL && W<HexSize-2) // Need space for 2 chars and final zero.
  163. {
  164. HexW[W++]=HighHex;
  165. HexW[W++]=LowHex;
  166. }
  167. }
  168. if (HexA!=NULL && HexSize>0)
  169. HexA[A]=0;
  170. if (HexW!=NULL && HexSize>0)
  171. HexW[W]=0;
  172. }
  173. #ifndef SFX_MODULE
  174. uint GetDigits(uint Number)
  175. {
  176. uint Digits=1;
  177. while (Number>=10)
  178. {
  179. Number/=10;
  180. Digits++;
  181. }
  182. return Digits;
  183. }
  184. #endif
  185. bool LowAscii(const char *Str)
  186. {
  187. for (size_t I=0;Str[I]!=0;I++)
  188. if (/*(byte)Str[I]<32 || */(byte)Str[I]>127)
  189. return false;
  190. return true;
  191. }
  192. bool LowAscii(const wchar *Str)
  193. {
  194. for (size_t I=0;Str[I]!=0;I++)
  195. {
  196. // We convert wchar_t to uint just in case if some compiler
  197. // uses signed wchar_t.
  198. if (/*(uint)Str[I]<32 || */(uint)Str[I]>127)
  199. return false;
  200. }
  201. return true;
  202. }
  203. int wcsicompc(const wchar *s1,const wchar *s2) // For path comparison.
  204. {
  205. #if defined(_UNIX)
  206. return wcscmp(s1,s2);
  207. #else
  208. return wcsicomp(s1,s2);
  209. #endif
  210. }
  211. int wcsnicompc(const wchar *s1,const wchar *s2,size_t n)
  212. {
  213. #if defined(_UNIX)
  214. return wcsncmp(s1,s2,n);
  215. #else
  216. return wcsnicomp(s1,s2,n);
  217. #endif
  218. }
  219. // Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest.
  220. void strncpyz(char *dest, const char *src, size_t maxlen)
  221. {
  222. if (maxlen>0)
  223. {
  224. while (--maxlen>0 && *src!=0)
  225. *dest++=*src++;
  226. *dest=0;
  227. }
  228. }
  229. // Safe copy: copies maxlen-1 max and for maxlen>0 returns zero terminated dest.
  230. void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
  231. {
  232. if (maxlen>0)
  233. {
  234. while (--maxlen>0 && *src!=0)
  235. *dest++=*src++;
  236. *dest=0;
  237. }
  238. }
  239. // Safe append: resulting dest length cannot exceed maxlen and dest
  240. // is always zero terminated. 'maxlen' parameter defines the entire
  241. // dest buffer size and is not compatible with wcsncat.
  242. void strncatz(char* dest, const char* src, size_t maxlen)
  243. {
  244. size_t length = strlen(dest);
  245. if (maxlen > length)
  246. strncpyz(dest + length, src, maxlen - length);
  247. }
  248. // Safe append: resulting dest length cannot exceed maxlen and dest
  249. // is always zero terminated. 'maxlen' parameter defines the entire
  250. // dest buffer size and is not compatible with wcsncat.
  251. void wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
  252. {
  253. size_t length = wcslen(dest);
  254. if (maxlen > length)
  255. wcsncpyz(dest + length, src, maxlen - length);
  256. }
  257. void itoa(int64 n,char *Str,size_t MaxSize)
  258. {
  259. char NumStr[50];
  260. size_t Pos=0;
  261. int Neg=n < 0 ? 1 : 0;
  262. if (Neg)
  263. n=-n;
  264. do
  265. {
  266. if (Pos+1>=MaxSize-Neg)
  267. break;
  268. NumStr[Pos++]=char(n%10)+'0';
  269. n=n/10;
  270. } while (n!=0);
  271. if (Neg)
  272. NumStr[Pos++]='-';
  273. for (size_t I=0;I<Pos;I++)
  274. Str[I]=NumStr[Pos-I-1];
  275. Str[Pos]=0;
  276. }
  277. void itoa(int64 n,wchar *Str,size_t MaxSize)
  278. {
  279. wchar NumStr[50];
  280. size_t Pos=0;
  281. int Neg=n < 0 ? 1 : 0;
  282. if (Neg)
  283. n=-n;
  284. do
  285. {
  286. if (Pos+1>=MaxSize-Neg)
  287. break;
  288. NumStr[Pos++]=wchar(n%10)+'0';
  289. n=n/10;
  290. } while (n!=0);
  291. if (Neg)
  292. NumStr[Pos++]='-';
  293. for (size_t I=0;I<Pos;I++)
  294. Str[I]=NumStr[Pos-I-1];
  295. Str[Pos]=0;
  296. }
  297. const wchar* GetWide(const char *Src)
  298. {
  299. const size_t MaxLength=NM;
  300. static wchar StrTable[4][MaxLength];
  301. static uint StrNum=0;
  302. if (++StrNum >= ASIZE(StrTable))
  303. StrNum=0;
  304. wchar *Str=StrTable[StrNum];
  305. CharToWide(Src,Str,MaxLength);
  306. Str[MaxLength-1]=0;
  307. return Str;
  308. }
  309. // Parse string containing parameters separated with spaces.
  310. // Support quote marks. Param can be NULL to return the pointer to next
  311. // parameter, which can be used to estimate the buffer size for Param.
  312. const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize)
  313. {
  314. while (IsSpace(*CmdLine))
  315. CmdLine++;
  316. if (*CmdLine==0)
  317. return NULL;
  318. size_t ParamSize=0;
  319. bool Quote=false;
  320. while (*CmdLine!=0 && (Quote || !IsSpace(*CmdLine)))
  321. {
  322. if (*CmdLine=='\"')
  323. {
  324. if (CmdLine[1]=='\"')
  325. {
  326. // Insert the quote character instead of two adjoining quote characters.
  327. if (Param!=NULL && ParamSize<MaxSize-1)
  328. Param[ParamSize++]='\"';
  329. CmdLine++;
  330. }
  331. else
  332. Quote=!Quote;
  333. }
  334. else
  335. if (Param!=NULL && ParamSize<MaxSize-1)
  336. Param[ParamSize++]=*CmdLine;
  337. CmdLine++;
  338. }
  339. if (Param!=NULL)
  340. Param[ParamSize]=0;
  341. return CmdLine;
  342. }
  343. #ifndef RARDLL
  344. // For compatibility with existing translations we use %s to print Unicode
  345. // strings in format strings and convert them to %ls here. %s could work
  346. // without such conversion in Windows, but not in Unix wprintf.
  347. void PrintfPrepareFmt(const wchar *Org,wchar *Cvt,size_t MaxSize)
  348. {
  349. uint Src=0,Dest=0;
  350. while (Org[Src]!=0 && Dest<MaxSize-1)
  351. {
  352. if (Org[Src]=='%' && (Src==0 || Org[Src-1]!='%'))
  353. {
  354. uint SPos=Src+1;
  355. // Skipping a possible width specifier like %-50s.
  356. while (IsDigit(Org[SPos]) || Org[SPos]=='-')
  357. SPos++;
  358. if (Org[SPos]=='s' && Dest<MaxSize-(SPos-Src+1))
  359. {
  360. while (Src<SPos)
  361. Cvt[Dest++]=Org[Src++];
  362. Cvt[Dest++]='l';
  363. }
  364. }
  365. #ifdef _WIN_ALL
  366. // Convert \n to \r\n in Windows. Important when writing to log,
  367. // so other tools like Notebook can view resulting log properly.
  368. if (Org[Src]=='\n' && (Src==0 || Org[Src-1]!='\r'))
  369. Cvt[Dest++]='\r';
  370. #endif
  371. Cvt[Dest++]=Org[Src++];
  372. }
  373. Cvt[Dest]=0;
  374. }
  375. #endif