Upstream tarball 20080630
[amule.git] / src / libs / common / StringFunctions.cpp
blob57a03c29c459296fd584f2c7b553bbbb31673ffe
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2004-2008 Angel Vidal ( kry@amule.org )
5 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
6 //
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
9 // respective authors.
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.
20 //
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"
31 #include "Path.h"
33 #include <wx/filename.h> // Needed for wxFileName
34 #include <wx/uri.h> // Needed for wxURI
36 // Implementation of the non-inlines
37 static byte base16Chars[17] = "0123456789ABCDEF";
39 wxString URLEncode(const wxString& sIn)
41 wxString sOut;
42 unsigned char curChar;
44 for ( unsigned int i = 0; i < sIn.Length(); ++i ) {
45 curChar = sIn.GetChar( i );
47 if ( isalnum( curChar ) ) {
48 sOut += curChar;
49 } else if( isspace ( curChar ) ) {
50 sOut += wxT("+");
51 } else {
52 sOut += wxT("%");
53 sOut += base16Chars[ curChar >> 4];
54 sOut += base16Chars[ curChar & 0xf];
59 return sOut;
62 wxString TruncateFilename(const CPath& filename, size_t length, bool isFilePath)
64 wxString file = filename.GetPrintable();
66 // Check if there's anything to do
67 if (file.Length() <= length)
68 return file;
70 // If the filename is a path, then prefer to remove from the path, rather than the filename
71 if ( isFilePath ) {
72 wxString path = wxFileName(file).GetPath();
73 file = wxFileName(file).GetFullName();
75 if ( path.Length() >= length ) {
76 path.Clear();
77 } else if ( file.Length() >= length ) {
78 path.Clear();
79 } else {
80 // Minus 6 for "[...]" + separator
81 int pathlen = (int)(length - file.Length() - 6);
83 if ( pathlen > 0 ) {
84 path = wxT("[...]") + path.Right( pathlen );
85 } else {
86 path.Clear();
90 file = JoinPaths(path, file);
93 if ( file.Length() > length ) {
94 if ( length > 5 ) {
95 file = file.Left( length - 5 ) + wxT("[...]");
96 } else {
97 file.Clear();
102 return file;
107 wxString StripSeparators(wxString path, wxString::stripType type)
109 wxASSERT((type == wxString::leading) || (type == wxString::trailing));
110 const wxString seps = wxFileName::GetPathSeparators();
112 while (!path.IsEmpty()) {
113 size_t pos = ((type == wxString::leading) ? 0 : path.Length() - 1);
115 if (seps.Contains(path.GetChar(pos))) {
116 path.Remove(pos, 1);
117 } else {
118 break;
122 return path;
126 wxString JoinPaths(const wxString& path, const wxString& file)
128 if (path.IsEmpty()) {
129 return file;
130 } else if (file.IsEmpty()) {
131 return path;
134 return StripSeparators(path, wxString::trailing)
135 + wxFileName::GetPathSeparator()
136 + StripSeparators(file, wxString::leading);
140 wxChar HexToDec( const wxString& hex )
142 wxChar result = 0;
143 wxString str = hex.Upper();
145 for ( size_t i = 0; i < str.Len(); ++i ) {
146 result *= 16;
147 wxChar cur = str.GetChar(i);
149 if ( isdigit( cur ) ) {
150 result += cur - wxT('0');
151 } else if ( cur >= wxT('A') && cur <= wxT('F') ) {
152 result += cur - wxT('A') + 10;
153 } else {
154 return wxT('\0');
158 return result;
162 wxString UnescapeHTML( const wxString& str )
164 wxString result;
165 result.Alloc( str.Len() );
167 for ( size_t i = 0; i < str.Len(); ++i ) {
168 if ( str.GetChar(i) == wxT('%') && ( i + 2 < str.Len() ) ) {
169 wxChar unesc = HexToDec( str.Mid( i + 1, 2 ) );
171 if ( unesc ) {
172 i += 2;
174 result += unesc;
175 } else {
176 // If conversion failed, then we just add the escape-code
177 // and continue past it like nothing happened.
178 result += str.at(i);
180 } else {
181 result += str.at(i);
185 return result;
189 wxString validateURI(const wxString& url)
191 wxURI uri(url);
193 return uri.BuildURI();
197 enum ECharType {
198 ECTInteger,
199 ECTText,
200 ECTNone
203 inline wxString GetNextField(const wxString& str, size_t& cookie)
205 // These are taken to seperate "fields"
206 static const wxChar* s_delims = wxT("\t\n\x0b\x0c\r !\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~");
208 wxString field;
209 ECharType curType = ECTNone;
210 for (; cookie < str.Length(); ++cookie) {
211 wxChar c = str[cookie];
213 if ((c >= wxT('0')) && (c <= wxT('9'))) {
214 if (curType == ECTText) {
215 break;
218 curType = ECTInteger;
219 field += c;
220 } else if (wxStrchr(s_delims, c)) {
221 if (curType == ECTNone) {
222 continue;
223 } else {
224 break;
226 } else {
227 if (curType == ECTInteger) {
228 break;
231 curType = ECTText;
232 field += c;
236 return field;
240 int FuzzyStrCmp(const wxString& a, const wxString& b)
242 size_t aCookie = 0, bCookie = 0;
243 wxString aField, bField;
245 do {
246 aField = GetNextField(a, aCookie);
247 bField = GetNextField(b, bCookie);
249 if (aField.IsNumber() && bField.IsNumber()) {
250 unsigned long aInteger = StrToULong(aField);
251 unsigned long bInteger = StrToULong(bField);
253 if (aInteger < bInteger) {
254 return -1;
255 } else if (aInteger > bInteger) {
256 return 1;
258 } else if (aField < bField) {
259 return -1;
260 } else if (aField > bField) {
261 return 1;
263 } while (!aField.IsEmpty() && !bField.IsEmpty());
265 return 0;
269 int FuzzyStrCaseCmp(const wxString& a, const wxString& b)
271 return FuzzyStrCmp(a.Lower(), b.Lower());
276 CSimpleTokenizer::CSimpleTokenizer(const wxString& str, wxChar token)
277 : m_string(str),
278 m_delim(token),
279 m_ptr(m_string.c_str()),
280 m_count(0)
285 wxString CSimpleTokenizer::next()
287 const wxChar* start = m_ptr;
288 const wxChar* end = m_string.c_str() + m_string.Len() + 1;
290 for (; m_ptr < end; ++m_ptr) {
291 if (*m_ptr == m_delim) {
292 m_count++;
293 break;
297 // Return the token
298 return m_string.Mid(start - m_string.c_str(), m_ptr++ - start);
302 wxString CSimpleTokenizer::remaining() const
304 return m_string.Mid(m_ptr - m_string.c_str());
308 size_t CSimpleTokenizer::tokenCount() const
310 return m_count;
314 // File_checked_for_headers