8 #include "BitTwiddle.hpp"
9 #include "MatchWildcard.hpp"
12 #include "Environment.h"
13 #include "ErrnoSaver.hpp"
14 #include "PlatformConstants.h"
16 #include "IntStrConv.h"
18 #define MAKE_STR(x) _MAKE_STR(x)
19 #define _MAKE_STR(x) #x
22 # define st_mtim st_mtimespec
23 # define st_ctim st_ctimespec
24 # define st_atim st_atimespec
27 template <class C
> static size_t tzlen(const C
*ptz
)
30 for (etz
= ptz
; *etz
; ++etz
);
34 template <class C
> static size_t tnzlen(const C
*ptz
, size_t n
)
37 for (i
= 0; i
< n
&& ptz
[i
]; ++i
);
41 // converts given hex digit to value between 0x0 and 0xf
42 // in case of error returns 0xff
43 template <class CHAR_T
>
44 unsigned char ParseHexDigit(const CHAR_T hex
)
46 if (hex
>= (CHAR_T
)'0' && hex
<= (CHAR_T
)'9')
47 return hex
- (CHAR_T
)'0';
48 if (hex
>= (CHAR_T
)'a' && hex
<= (CHAR_T
)'f')
49 return 10 + hex
- (CHAR_T
)'a';
50 if (hex
>= (CHAR_T
)'A' && hex
<= (CHAR_T
)'F')
51 return 10 + hex
- (CHAR_T
)'A';
56 // converts given two hex digits to value between 0x0 and 0xff
57 // in case of error returns 0
58 template <class CHAR_T
>
59 unsigned char ParseHexByte(const CHAR_T
*hex
)
61 const unsigned char rh
= ParseHexDigit(hex
[0]);
62 const unsigned char rl
= ParseHexDigit(hex
[1]);
63 if (rh
== 0xff || rl
== 0xff) {
66 return ((rh
<< 4) | rl
);
70 // converts given value between 0x0 and 0xf to lowercased hex digit
71 // in case of error returns 0
72 char MakeHexDigit(const unsigned char c
);
75 size_t StrStartsFrom(const StrT
&haystack
, const typename
StrT::value_type needle
)
77 return (!haystack
.empty() && haystack
.front() == needle
) ? 1 : 0;
80 template <class CharT
>
81 size_t StrStartsFrom(const CharT
*haystack
, const CharT
*needle
)
84 for (i
= 0; needle
[i
]; ++i
) {
85 if (haystack
[i
] != needle
[i
])
92 size_t StrStartsFrom(const StrT
&haystack
, const typename
StrT::value_type
*needle
)
95 for (i
= 0; needle
[i
]; ++i
) {
96 if (i
>= haystack
.size() || haystack
[i
] != needle
[i
])
102 template <class StrT
>
103 size_t StrEndsBy(const StrT
&haystack
, const typename
StrT::value_type
*needle
)
105 const size_t l
= tzlen(needle
);
106 if (!l
|| haystack
.size() < l
)
109 return memcmp(haystack
.c_str() + haystack
.size() - l
, needle
, l
* sizeof(typename
StrT::value_type
)) ? 0 : l
;
112 template <class StrT
>
113 size_t StrEndsBy(const StrT
&haystack
, const typename
StrT::value_type needle
)
115 return !haystack
.empty() && haystack
.back() == needle
;
119 const std::string
&GetMyHome();
121 void InMyPathChanged(); // NOT thread safe, can be called only before any concurrent use of InMy...
122 std::string
InMyConfig(const char *subpath
= NULL
, bool create_path
= true);
123 std::string
InMyCache(const char *subpath
= NULL
, bool create_path
= true);
124 std::string
InMyTemp(const char *subpath
= NULL
);
126 bool IsPathIn(const wchar_t *path
, const wchar_t *root
);
128 bool TranslateInstallPath_Bin2Share(std::wstring
&path
);
129 bool TranslateInstallPath_Bin2Share(std::string
&path
);
130 bool TranslateInstallPath_Lib2Share(std::wstring
&path
);
131 bool TranslateInstallPath_Lib2Share(std::string
&path
);
132 bool TranslateInstallPath_Share2Lib(std::wstring
&path
);
133 bool TranslateInstallPath_Share2Lib(std::string
&path
);
134 bool TranslateInstallPath_Bin2Lib(std::string
&path
);
137 // converts /some/path/to/filename.extension into form "filename@HASH"
138 // where HASH produced from path and extension and also filename has
139 // some special for ini files chars replaced by '_' and affected HASH
140 void FilePathHashSuffix(std::string
&pathname
);
142 void CheckedCloseFD(int &fd
);
143 void CheckedCloseFDPair(int *fd
);
145 void MakeFDBlocking(int fd
);
146 void MakeFDNonBlocking(int fd
);
147 void MakeFDCloexec(int fd
);
148 void MakeFDNonCloexec(int fd
);
149 void HintFDSequentialAccess(int fd
);
151 size_t WriteAll(int fd
, const void *data
, size_t len
, size_t chunk
= (size_t)-1);
152 size_t ReadAll(int fd
, void *data
, size_t len
);
153 ssize_t
ReadWritePiece(int fd_src
, int fd_dst
);
155 bool ReadWholeFile(const char *path
, std::string
&result
, size_t limit
= (size_t)-1);
157 int pipe_cloexec(int pipedes
[2]);
159 void PutZombieUnderControl(pid_t pid
);
161 void AbbreviateString(std::string
&path
, size_t needed_length
);
163 const wchar_t *FileSizeToFractionAndUnits(unsigned long long &value
);
164 std::wstring
FileSizeString(unsigned long long value
);
165 std::wstring
ThousandSeparatedString(unsigned long long value
);
167 std::string
StrPrintfV(const char *format
, va_list args
);
168 std::string
FN_PRINTF_ARGS(1) StrPrintf(const char *format
, ...);
170 template <class CharT
>
171 std::basic_string
<CharT
> EnsureNoSlashAtEnd(std::basic_string
<CharT
> str
, CharT slash
= '/')
173 for (size_t p
= str
.size(); p
&& str
[p
- 1] == slash
; ) {
179 template <class CharT
>
180 std::basic_string
<CharT
> EnsureNoSlashAtNestedEnd(std::basic_string
<CharT
> str
, CharT slash
= '/')
182 for (size_t p
= str
.size(); p
> 1 && str
[p
- 1] == slash
; ) {
189 template <class CharT
>
190 std::basic_string
<CharT
> EnsureSlashAtEnd(std::basic_string
<CharT
> str
, CharT slash
= '/')
192 const size_t p
= str
.size();
193 if (!p
|| str
[p
- 1] != slash
) {
199 template <class CharT
>
200 std::basic_string
<CharT
> ExtractFilePath(std::basic_string
<CharT
> str
, CharT slash
= '/')
202 const size_t p
= str
.rfind(slash
);
203 str
.resize( (p
!= std::string::npos
) ? p
: 0);
208 template <class CharT
>
209 std::basic_string
<CharT
> ExtractFileName(std::basic_string
<CharT
> str
, CharT slash
= '/')
211 const size_t p
= str
.rfind(slash
);
212 return (p
!= std::string::npos
) ? str
.substr( p
+ 1, str
.size() - (p
+ 1) ) : str
;
216 template <class CharT
>
217 bool CutToSlash(std::basic_string
<CharT
> &str
, bool include
= false)
219 size_t p
= str
.rfind('/');
220 if (p
== std::string::npos
)
223 str
.resize(include
? p
+ 1 : p
);
227 template <class CharT
>
228 void ReplaceFileNamePart(std::basic_string
<CharT
> &str
, const CharT
*replacement
)
230 if (CutToSlash(str
, true)) {
238 template <class CharT
>
239 void StrExplode(std::vector
<std::basic_string
<CharT
> > &out
, const std::basic_string
<CharT
> &str
, const CharT
*divs
)
241 for (size_t i
= 0, j
= 0; i
<= str
.size(); ++i
) {
242 const CharT
*d
= divs
;
243 if (i
!= str
.size()) {
244 for (; *d
&& *d
!= str
[i
]; ++d
);
248 out
.emplace_back(str
.substr(j
, i
- j
));
255 template <class CharT
>
256 void StrTrimRight(std::basic_string
<CharT
> &str
, const char *spaces
= " \t")
258 while (!str
.empty() && unsigned(str
.back()) <= 0x7f && strchr(spaces
, str
.back()) != NULL
) {
262 template <class CharT
>
263 void StrTrimLeft(std::basic_string
<CharT
> &str
, const char *spaces
= " \t")
265 while (!str
.empty() && unsigned(str
[0]) <= 0x7f && strchr(spaces
, str
[0]) != NULL
) {
270 template <class CharT
>
271 void StrTrim(std::basic_string
<CharT
> &str
, const char *spaces
= " \t")
273 StrTrimRight(str
, spaces
);
274 StrTrimLeft(str
, spaces
);
278 template <typename HaystackT
, typename NeedlesT
>
279 static const HaystackT
*FindAnyOfChars(const HaystackT
*haystack
, const NeedlesT
*needles
)
281 for(; *haystack
; ++haystack
)
283 for(size_t i
= 0; needles
[i
]; ++i
)
285 if (*haystack
== (HaystackT
)needles
[i
])
292 template <typename HaystackIT
, typename NeedlesT
>
293 static HaystackIT
FindAnyOfChars(HaystackIT haystack
, const HaystackIT haystack_end
, const NeedlesT
*needles
)
295 for(; haystack
!= haystack_end
; ++haystack
)
297 for(size_t i
= 0; needles
[i
]; ++i
)
299 if (*haystack
== (decltype(*haystack
))needles
[i
])
306 bool CaseIgnoreEngStrMatch(const std::string
&str1
, const std::string
&str2
);
307 bool CaseIgnoreEngStrMatch(const char *str1
, const char *str2
, size_t len
);
308 const char *CaseIgnoreEngStrChr(const char c
, const char *str
, size_t len
);
310 template <class STRING_T
, typename ARRAY_T
>
311 void StrAssignArray(STRING_T
&s
, const ARRAY_T
&a
)
313 static_assert ( sizeof(a
) != sizeof(void *), "StrAssignArray should be used with arrays but not pointers");
314 s
.assign(a
, tnzlen(a
, ARRAYSIZE(a
)));
317 template <class STRING_T
, typename ARRAY_T
>
318 void StrAppendArray(STRING_T
&s
, const ARRAY_T
&a
)
320 static_assert ( sizeof(a
) != sizeof(void *), "StrAppendArray should be used with arrays but not pointers");
321 s
.append(a
, tnzlen(a
, ARRAYSIZE(a
)));
325 template <class STRING_T
, typename ARRAY_T
>
326 bool StrMatchArray(STRING_T
&s
, const ARRAY_T
&a
)
328 static_assert ( sizeof(a
) != sizeof(void *), "StrMatchArray should be used with arrays but not pointers");
329 const size_t l
= tnzlen(a
, ARRAYSIZE(a
));
330 return s
.size() == l
&& s
.compare(0, std::string::npos
, a
, l
) == 0;
333 template <typename ARRAY_T
, class CHAR_T
>
334 void ArrayCpyZ(ARRAY_T
&dst
, const CHAR_T
*src
)
336 static_assert ( sizeof(dst
) != sizeof(void *), "ArrayCpyZ should be used with arrays but not pointers");
338 for (i
= 0; src
[i
] && i
+ 1 < ARRAYSIZE(dst
); ++i
) {
345 bool POpen(std::string
&result
, const char *command
);
346 bool POpen(std::vector
<std::wstring
> &result
, const char *command
);
348 #define DBGLINE fprintf(stderr, "%d %d @%s\n", getpid(), __LINE__, __FILE__)
350 bool IsCharFullWidth(wchar_t c
);
351 bool IsCharPrefix(wchar_t c
);
352 bool IsCharSuffix(wchar_t c
);
353 bool IsCharXxxfix(wchar_t c
);
355 void FN_NORETURN
FN_PRINTF_ARGS(1) ThrowPrintf(const char *format
, ...); // throws std::runtime_error with formatted .what()