1 #include "rar.hpp"
2 
NullToEmpty(const char * Str)3 const char *NullToEmpty(const char *Str)
4 {
5   return(Str==NULL ? "":Str);
6 }
7 
8 
NullToEmpty(const wchar * Str)9 const wchar *NullToEmpty(const wchar *Str)
10 {
11   return(Str==NULL ? L"":Str);
12 }
13 
14 
15 
16 
IntNameToExt(const char * Name)17 char *IntNameToExt(const char *Name)
18 {
19   return NULL;
20 }
21 
22 
ExtToInt(const char * Src,char * Dest)23 void ExtToInt(const char *Src,char *Dest)
24 {
25 #ifdef _WIN_ALL
26   CharToOemA(Src,Dest);
27 #else
28   if (Dest!=Src)
29     strcpy(Dest,Src);
30 #endif
31 }
32 
33 
IntToExt(const char * Src,char * Dest)34 void IntToExt(const char *Src,char *Dest)
35 {
36 #ifdef _WIN_ALL
37   OemToCharA(Src,Dest);
38 #else
39   if (Dest!=Src)
40     strcpy(Dest,Src);
41 #endif
42 }
43 
44 
strlower(char * Str)45 char* strlower(char *Str)
46 {
47 #ifdef _WIN_ALL
48   CharLowerA((LPSTR)Str);
49 #else
50   for (char *ChPtr=Str;*ChPtr;ChPtr++)
51     *ChPtr=(char)loctolower(*ChPtr);
52 #endif
53   return(Str);
54 }
55 
56 
strupper(char * Str)57 char* strupper(char *Str)
58 {
59 #ifdef _WIN_ALL
60   CharUpperA((LPSTR)Str);
61 #else
62   for (char *ChPtr=Str;*ChPtr;ChPtr++)
63     *ChPtr=(char)loctoupper(*ChPtr);
64 #endif
65   return(Str);
66 }
67 
68 
stricomp(const char * Str1,const char * Str2)69 int stricomp(const char *Str1,const char *Str2)
70 {
71   char S1[NM*2],S2[NM*2];
72   strncpyz(S1,Str1,ASIZE(S1));
73   strncpyz(S2,Str2,ASIZE(S2));
74   return(strcmp(strupper(S1),strupper(S2)));
75 }
76 
77 
strnicomp(const char * Str1,const char * Str2,size_t N)78 int strnicomp(const char *Str1,const char *Str2,size_t N)
79 {
80   char S1[NM*2],S2[NM*2];
81   strncpyz(S1,Str1,ASIZE(S1));
82   strncpyz(S2,Str2,ASIZE(S2));
83   return(strncmp(strupper(S1),strupper(S2),N));
84 }
85 
86 
RemoveEOL(char * Str)87 char* RemoveEOL(char *Str)
88 {
89   for (int I=(int)strlen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n' || Str[I]==' ' || Str[I]=='\t');I--)
90     Str[I]=0;
91   return(Str);
92 }
93 
94 
RemoveLF(char * Str)95 char* RemoveLF(char *Str)
96 {
97   for (int I=(int)strlen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--)
98     Str[I]=0;
99   return(Str);
100 }
101 
102 
RemoveLF(wchar * Str)103 wchar* RemoveLF(wchar *Str)
104 {
105   for (int I=(int)wcslen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--)
106     Str[I]=0;
107   return(Str);
108 }
109 
110 
loctolower(unsigned char ch)111 unsigned char loctolower(unsigned char ch)
112 {
113   return(tolower(ch));
114 }
115 
116 
loctoupper(unsigned char ch)117 unsigned char loctoupper(unsigned char ch)
118 {
119   return(toupper(ch));
120 }
121 
122 
123 // toupper with English only results if English input is provided.
124 // It avoids Turkish (small i) -> (big I with dot) conversion problem.
125 // We do not define 'ch' as 'int' to avoid necessity to cast all
126 // signed chars passed to this function to unsigned char.
etoupper(unsigned char ch)127 unsigned char etoupper(unsigned char ch)
128 {
129   if (ch=='i')
130     return('I');
131   return(toupper(ch));
132 }
133 
134 
135 // Unicode version of etoupper.
etoupperw(wchar ch)136 wchar etoupperw(wchar ch)
137 {
138   if (ch=='i')
139     return('I');
140   return(toupperw(ch));
141 }
142 
143 
144 // We do not want to cast every signed char to unsigned when passing to
145 // isdigit, so we implement the replacement. Shall work for Unicode too.
146 // If chars are signed, conversion from char to int could generate negative
147 // values, resulting in undefined behavior in standard isdigit.
IsDigit(int ch)148 bool IsDigit(int ch)
149 {
150   return(ch>='0' && ch<='9');
151 }
152 
153 
154 // We do not want to cast every signed char to unsigned when passing to
155 // isspace, so we implement the replacement. Shall work for Unicode too.
156 // If chars are signed, conversion from char to int could generate negative
157 // values, resulting in undefined behavior in standard isspace.
IsSpace(int ch)158 bool IsSpace(int ch)
159 {
160   return(ch==' ' || ch=='\t');
161 }
162 
163 
164 // We do not want to cast every signed char to unsigned when passing to
165 // isalpha, so we implement the replacement. Shall work for Unicode too.
166 // If chars are signed, conversion from char to int could generate negative
167 // values, resulting in undefined behavior in standard function.
IsAlpha(int ch)168 bool IsAlpha(int ch)
169 {
170   return((ch>='A' && ch<='Z') || (ch>='a' && ch<='z'));
171 }
172 
173 
174 
175 
176 #ifndef SFX_MODULE
GetDigits(uint Number)177 uint GetDigits(uint Number)
178 {
179   uint Digits=1;
180   while (Number>=10)
181   {
182     Number/=10;
183     Digits++;
184   }
185   return(Digits);
186 }
187 #endif
188 
189 
LowAscii(const char * Str)190 bool LowAscii(const char *Str)
191 {
192   for (int I=0;Str[I]!=0;I++)
193     if ((byte)Str[I]<32 || (byte)Str[I]>127)
194       return(false);
195   return(true);
196 }
197 
198 
LowAscii(const wchar * Str)199 bool LowAscii(const wchar *Str)
200 {
201   for (int I=0;Str[I]!=0;I++)
202   {
203     // We convert wchar_t to uint just in case if some compiler
204     // uses the signed wchar_t.
205     if ((uint)Str[I]<32 || (uint)Str[I]>127)
206       return(false);
207   }
208   return(true);
209 }
210 
211 
212 
213 
stricompc(const char * Str1,const char * Str2)214 int stricompc(const char *Str1,const char *Str2)
215 {
216 #if defined(_UNIX)
217   return(strcmp(Str1,Str2));
218 #else
219   return(stricomp(Str1,Str2));
220 #endif
221 }
222 
223 
224 #ifndef SFX_MODULE
wcsicompc(const wchar * Str1,const wchar * Str2)225 int wcsicompc(const wchar *Str1,const wchar *Str2)
226 {
227 #if defined(_UNIX)
228   return(wcscmp(Str1,Str2));
229 #else
230   return(wcsicomp(Str1,Str2));
231 #endif
232 }
233 #endif
234 
235 
236 // safe strncpy: copies maxlen-1 max and always returns zero terminated dest
strncpyz(char * dest,const char * src,size_t maxlen)237 char* strncpyz(char *dest, const char *src, size_t maxlen)
238 {
239   if (maxlen>0)
240   {
241     strncpy(dest,src,maxlen-1);
242     dest[maxlen-1]=0;
243   }
244   return(dest);
245 }
246 
247 
248 // Safe wcsncpy: copies maxlen-1 max and always returns zero terminated dest.
wcsncpyz(wchar * dest,const wchar * src,size_t maxlen)249 wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
250 {
251   if (maxlen>0)
252   {
253     wcsncpy(dest,src,maxlen-1);
254     dest[maxlen-1]=0;
255   }
256   return(dest);
257 }
258 
259 
260 // Safe strncat: resulting dest length cannot exceed maxlen and dest
261 // is always zero terminated. Note that 'maxlen' parameter defines the entire
262 // dest buffer size and is not compatible with standard strncat.
strncatz(char * dest,const char * src,size_t maxlen)263 char* strncatz(char* dest, const char* src, size_t maxlen)
264 {
265   size_t Length = strlen(dest);
266   if (Length + 1 < maxlen)
267     strncat(dest, src, maxlen - Length - 1);
268   return dest;
269 }
270 
271 
272 // Safe wcsncat: resulting dest length cannot exceed maxlen and dest
273 // is always zero terminated. Note that 'maxlen' parameter defines the entire
274 // dest buffer size and is not compatible with standard wcsncat.
wcsncatz(wchar * dest,const wchar * src,size_t maxlen)275 wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
276 {
277   size_t Length = wcslen(dest);
278   if (Length + 1 < maxlen)
279     wcsncat(dest, src, maxlen - Length - 1);
280   return dest;
281 }
282 
283 
itoa(int64 n,char * Str)284 void itoa(int64 n,char *Str)
285 {
286   char NumStr[50];
287   size_t Pos=0;
288 
289   do
290   {
291     NumStr[Pos++]=char(n%10)+'0';
292     n=n/10;
293   } while (n!=0);
294 
295   for (size_t I=0;I<Pos;I++)
296     Str[I]=NumStr[Pos-I-1];
297   Str[Pos]=0;
298 }
299 
300 
301 
atoil(const char * Str)302 int64 atoil(const char *Str)
303 {
304   int64 n=0;
305   while (*Str>='0' && *Str<='9')
306   {
307     n=n*10+*Str-'0';
308     Str++;
309   }
310   return(n);
311 }
312 
313 
itoa(int64 n,wchar * Str)314 void itoa(int64 n,wchar *Str)
315 {
316   wchar NumStr[50];
317   size_t Pos=0;
318 
319   do
320   {
321     NumStr[Pos++]=wchar(n%10)+'0';
322     n=n/10;
323   } while (n!=0);
324 
325   for (size_t I=0;I<Pos;I++)
326     Str[I]=NumStr[Pos-I-1];
327   Str[Pos]=0;
328 }
329 
330 
atoil(const wchar * Str)331 int64 atoil(const wchar *Str)
332 {
333   int64 n=0;
334   while (*Str>='0' && *Str<='9')
335   {
336     n=n*10+*Str-'0';
337     Str++;
338   }
339   return(n);
340 }
341 
342 
343 #ifdef DOES_NOT_LOOK_LIKE_WE_USE_GETWIDE
GetWide(const char * Src)344 const wchar* GetWide(const char *Src)
345 {
346   const size_t MaxLength=NM;
347   wchar StrTable[4][MaxLength];
348   uint StrNum=0;
349   if (++StrNum >= ASIZE(StrTable))
350     StrNum=0;
351   wchar *Str=StrTable[StrNum];
352   CharToWide(Src,Str,MaxLength);
353   Str[MaxLength-1]=0;
354   return(Str);
355 }
356 #endif
357 
358 
359 #ifdef _WIN_ALL
360 // Parse string containing parameters separated with spaces.
361 // Support quote marks. Param can be NULL to return the pointer to next
362 // parameter, which can be used to estimate the buffer size for Param.
GetCmdParam(const wchar * CmdLine,wchar * Param,size_t MaxSize)363 const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize)
364 {
365   while (IsSpace(*CmdLine))
366     CmdLine++;
367   if (*CmdLine==0)
368     return NULL;
369 
370   size_t ParamSize=0;
371   bool Quote=false;
372   while (*CmdLine!=0 && (Quote || !IsSpace(*CmdLine)))
373   {
374     if (*CmdLine=='\"')
375     {
376       if (CmdLine[1]=='\"')
377       {
378         // Insert the quote character instead of two adjoining quote characters.
379         if (Param!=NULL && ParamSize<MaxSize-1)
380           Param[ParamSize++]='\"';
381         CmdLine++;
382       }
383       else
384         Quote=!Quote;
385     }
386     else
387       if (Param!=NULL && ParamSize<MaxSize-1)
388         Param[ParamSize++]=*CmdLine;
389     CmdLine++;
390   }
391   if (Param!=NULL)
392     Param[ParamSize]=0;
393   return CmdLine;
394 }
395 #endif
396