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