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
26 #include "StringFunctions.h"
28 #include <wx/filename.h> // Needed for wxFileName
29 #include <wx/uri.h> // Needed for wxURI
31 // Implementation of the non-inlines
34 // Conversion of wxString so it can be used by printf() in a console
35 // On some platforms (Windows) the console allows only "plain" characters,
36 // so try to convert as much as possible and replace the others with '?'.
37 // On other platforms (some Linux) wxConvLocal silently converts to UTF8
38 // so the console can show even Chinese chars.
40 Unicode2CharBuf
unicode2char(const wxChar
* s
)
42 // First try the straight way.
43 Unicode2CharBuf
buf1(wxConvLocal
.cWX2MB(s
));
44 if ((const char *) buf1
) {
47 // Failed. Try to convert as much as possible.
48 size_t len
= wxStrlen(s
);
49 size_t maxlen
= len
* 4; // Allow for an encoding of up to 4 byte per char.
50 wxCharBuffer
buf(maxlen
+ 1); // This is wasteful, but the string is used temporary anyway.
51 char * data
= buf
.data();
52 for (size_t i
= 0, pos
= 0; i
< len
; i
++) {
53 size_t len_char
= wxConvLocal
.FromWChar(data
+ pos
, maxlen
- pos
, s
+ i
, 1);
54 if (len_char
!= wxCONV_FAILED
) {
56 } else if (pos
< maxlen
) {
65 static byte base16Chars
[17] = "0123456789ABCDEF";
67 wxString
URLEncode(const wxString
& sIn
)
70 unsigned char curChar
;
72 for ( unsigned int i
= 0; i
< sIn
.Length(); ++i
) {
73 curChar
= sIn
.GetChar( i
);
75 if ( isalnum( curChar
) ) {
77 } else if( isspace ( curChar
) ) {
81 sOut
+= base16Chars
[ curChar
>> 4];
82 sOut
+= base16Chars
[ curChar
& 0xf];
91 wxChar
HexToDec( const wxString
& hex
)
94 wxString str
= hex
.Upper();
96 for ( size_t i
= 0; i
< str
.Len(); ++i
) {
98 wxChar cur
= str
.GetChar(i
);
100 if ( isdigit( cur
) ) {
101 result
+= cur
- wxT('0');
102 } else if ( cur
>= wxT('A') && cur
<= wxT('F') ) {
103 result
+= cur
- wxT('A') + 10;
113 wxString
UnescapeHTML( const wxString
& str
)
116 result
.Alloc( str
.Len() );
118 for ( size_t i
= 0; i
< str
.Len(); ++i
) {
119 if ( str
.GetChar(i
) == wxT('%') && ( i
+ 2 < str
.Len() ) ) {
120 wxChar unesc
= HexToDec( str
.Mid( i
+ 1, 2 ) );
127 // If conversion failed, then we just add the escape-code
128 // and continue past it like nothing happened.
140 wxString
validateURI(const wxString
& url
)
144 return uri
.BuildURI();
154 inline wxString
GetNextField(const wxString
& str
, size_t& cookie
)
156 // These are taken to seperate "fields"
157 static const wxChar
* s_delims
= wxT("\t\n\x0b\x0c\r !\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~");
160 ECharType curType
= ECTNone
;
161 for (; cookie
< str
.Length(); ++cookie
) {
162 wxChar c
= str
[cookie
];
164 if ((c
>= wxT('0')) && (c
<= wxT('9'))) {
165 if (curType
== ECTText
) {
169 curType
= ECTInteger
;
171 } else if (wxStrchr(s_delims
, c
)) {
172 if (curType
== ECTNone
) {
178 if (curType
== ECTInteger
) {
191 int FuzzyStrCmp(const wxString
& a
, const wxString
& b
)
193 size_t aCookie
= 0, bCookie
= 0;
194 wxString aField
, bField
;
197 aField
= GetNextField(a
, aCookie
);
198 bField
= GetNextField(b
, bCookie
);
200 if (aField
.IsNumber() && bField
.IsNumber()) {
201 unsigned long aInteger
= StrToULong(aField
);
202 unsigned long bInteger
= StrToULong(bField
);
204 if (aInteger
< bInteger
) {
206 } else if (aInteger
> bInteger
) {
209 } else if (aField
< bField
) {
211 } else if (aField
> bField
) {
214 } while (!aField
.IsEmpty() && !bField
.IsEmpty());
220 int FuzzyStrCaseCmp(const wxString
& a
, const wxString
& b
)
222 return FuzzyStrCmp(a
.Lower(), b
.Lower());
227 CSimpleTokenizer::CSimpleTokenizer(const wxString
& str
, wxChar token
)
230 m_ptr(m_string
.c_str()),
236 wxString
CSimpleTokenizer::next()
238 const wxChar
* start
= m_ptr
;
239 const wxChar
* end
= m_string
.c_str() + m_string
.Len() + 1;
241 for (; m_ptr
< end
; ++m_ptr
) {
242 if (*m_ptr
== m_delim
) {
249 return m_string
.Mid(start
- m_string
.c_str(), m_ptr
++ - start
);
253 wxString
CSimpleTokenizer::remaining() const
255 return m_string
.Mid(m_ptr
- m_string
.c_str());
259 size_t CSimpleTokenizer::tokenCount() const