2 // This file is part of the aMule Project.
4 // Copyright (c) 2004-2008 Angel Vidal ( kry@amule.org )
5 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #define STRINGFUNCTIONS_CPP
30 #include "StringFunctions.h"
33 #include <wx/filename.h> // Needed for wxFileName
34 #include <wx/uri.h> // Needed for wxURI
36 // Implementation of the non-inlines
39 // Conversion of wxString so it can be used by printf() in a console
40 // On some platforms (Windows) the console allows only "plain" characters,
41 // so try to convert as much as possible and replace the others with '?'.
42 // On other platforms (some Linux) wxConvLocal silently converts to UTF8
43 // so the console can show even Chinese chars.
45 Unicode2CharBuf
unicode2char(const wxChar
* s
)
47 // First try the straight way.
48 Unicode2CharBuf
buf1(wxConvLocal
.cWX2MB(s
));
49 if ((const char *) buf1
) {
52 // Failed. Try to convert as much as possible.
53 size_t len
= wxStrlen(s
);
54 size_t maxlen
= len
* 4; // Allow for an encoding of up to 4 byte per char.
55 wxCharBuffer
buf(maxlen
+ 1); // This is wasteful, but the string is used temporary anyway.
56 char * data
= buf
.data();
57 for (size_t i
= 0, pos
= 0; i
< len
; i
++) {
58 size_t len_char
= wxConvLocal
.FromWChar(data
+ pos
, maxlen
- pos
, s
+ i
, 1);
59 if (len_char
!= wxCONV_FAILED
) {
61 } else if (pos
< maxlen
) {
69 static byte base16Chars
[17] = "0123456789ABCDEF";
71 wxString
URLEncode(const wxString
& sIn
)
74 unsigned char curChar
;
76 for ( unsigned int i
= 0; i
< sIn
.Length(); ++i
) {
77 curChar
= sIn
.GetChar( i
);
79 if ( isalnum( curChar
) ) {
81 } else if( isspace ( curChar
) ) {
85 sOut
+= base16Chars
[ curChar
>> 4];
86 sOut
+= base16Chars
[ curChar
& 0xf];
94 wxString
TruncateFilename(const CPath
& filename
, size_t length
, bool isFilePath
)
96 wxString file
= filename
.GetPrintable();
98 // Check if there's anything to do
99 if (file
.Length() <= length
)
102 // If the filename is a path, then prefer to remove from the path, rather than the filename
104 wxString path
= wxFileName(file
).GetPath();
105 file
= wxFileName(file
).GetFullName();
107 if ( path
.Length() >= length
) {
109 } else if ( file
.Length() >= length
) {
112 // Minus 6 for "[...]" + separator
113 int pathlen
= (int)(length
- file
.Length() - 6);
116 path
= wxT("[...]") + path
.Right( pathlen
);
122 file
= JoinPaths(path
, file
);
125 if ( file
.Length() > length
) {
127 file
= file
.Left( length
- 5 ) + wxT("[...]");
139 wxString
StripSeparators(wxString path
, wxString::stripType type
)
141 wxASSERT((type
== wxString::leading
) || (type
== wxString::trailing
));
142 const wxString seps
= wxFileName::GetPathSeparators();
144 while (!path
.IsEmpty()) {
145 size_t pos
= ((type
== wxString::leading
) ? 0 : path
.Length() - 1);
147 if (seps
.Contains(path
.GetChar(pos
))) {
158 wxString
JoinPaths(const wxString
& path
, const wxString
& file
)
160 if (path
.IsEmpty()) {
162 } else if (file
.IsEmpty()) {
166 return StripSeparators(path
, wxString::trailing
)
167 + wxFileName::GetPathSeparator()
168 + StripSeparators(file
, wxString::leading
);
172 wxChar
HexToDec( const wxString
& hex
)
175 wxString str
= hex
.Upper();
177 for ( size_t i
= 0; i
< str
.Len(); ++i
) {
179 wxChar cur
= str
.GetChar(i
);
181 if ( isdigit( cur
) ) {
182 result
+= cur
- wxT('0');
183 } else if ( cur
>= wxT('A') && cur
<= wxT('F') ) {
184 result
+= cur
- wxT('A') + 10;
194 wxString
UnescapeHTML( const wxString
& str
)
197 result
.Alloc( str
.Len() );
199 for ( size_t i
= 0; i
< str
.Len(); ++i
) {
200 if ( str
.GetChar(i
) == wxT('%') && ( i
+ 2 < str
.Len() ) ) {
201 wxChar unesc
= HexToDec( str
.Mid( i
+ 1, 2 ) );
208 // If conversion failed, then we just add the escape-code
209 // and continue past it like nothing happened.
221 wxString
validateURI(const wxString
& url
)
225 return uri
.BuildURI();
235 inline wxString
GetNextField(const wxString
& str
, size_t& cookie
)
237 // These are taken to seperate "fields"
238 static const wxChar
* s_delims
= wxT("\t\n\x0b\x0c\r !\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~");
241 ECharType curType
= ECTNone
;
242 for (; cookie
< str
.Length(); ++cookie
) {
243 wxChar c
= str
[cookie
];
245 if ((c
>= wxT('0')) && (c
<= wxT('9'))) {
246 if (curType
== ECTText
) {
250 curType
= ECTInteger
;
252 } else if (wxStrchr(s_delims
, c
)) {
253 if (curType
== ECTNone
) {
259 if (curType
== ECTInteger
) {
272 int FuzzyStrCmp(const wxString
& a
, const wxString
& b
)
274 size_t aCookie
= 0, bCookie
= 0;
275 wxString aField
, bField
;
278 aField
= GetNextField(a
, aCookie
);
279 bField
= GetNextField(b
, bCookie
);
281 if (aField
.IsNumber() && bField
.IsNumber()) {
282 unsigned long aInteger
= StrToULong(aField
);
283 unsigned long bInteger
= StrToULong(bField
);
285 if (aInteger
< bInteger
) {
287 } else if (aInteger
> bInteger
) {
290 } else if (aField
< bField
) {
292 } else if (aField
> bField
) {
295 } while (!aField
.IsEmpty() && !bField
.IsEmpty());
301 int FuzzyStrCaseCmp(const wxString
& a
, const wxString
& b
)
303 return FuzzyStrCmp(a
.Lower(), b
.Lower());
308 CSimpleTokenizer::CSimpleTokenizer(const wxString
& str
, wxChar token
)
311 m_ptr(m_string
.c_str()),
317 wxString
CSimpleTokenizer::next()
319 const wxChar
* start
= m_ptr
;
320 const wxChar
* end
= m_string
.c_str() + m_string
.Len() + 1;
322 for (; m_ptr
< end
; ++m_ptr
) {
323 if (*m_ptr
== m_delim
) {
330 return m_string
.Mid(start
- m_string
.c_str(), m_ptr
++ - start
);
334 wxString
CSimpleTokenizer::remaining() const
336 return m_string
.Mid(m_ptr
- m_string
.c_str());
340 size_t CSimpleTokenizer::tokenCount() const
346 // File_checked_for_headers