[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677
mjs
mjs at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 06:34:13 UTC 2009
The following commit has been merged in the debian/unstable branch:
commit 801d972bfe3d5ba1413017123b650cfe29dd9262
Author: mjs <mjs at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Fri Aug 23 03:39:31 2002 +0000
top level:
Fix test results to no longer reflect KURL or CFURL oddities that
we are not emulating.
* Tests/kde/kurl-test.chk:
* Tests/kde/kurl-test.cpp:
(testURL): Replay mistaken n with \n.
WebCore:
Brand new KURL implementation which avoids CFURL, CFString, and
all that other allocation-happy goodness and instead does as much
work as possible with raw ASCII buffers.
For me this gave a ~5% performance improvement on cvs-base.
* kwq/KWQKURL.mm:
(KURL::KURL):
(KURL::hasPath):
(KURL::protocol):
(KURL::host):
(KURL::port):
(KURL::pass):
(KURL::user):
(KURL::ref):
(KURL::query):
(KURL::path):
(KURL::setProtocol):
(KURL::setHost):
(KURL::setPort):
(KURL::setRef):
(KURL::setQuery):
(KURL::setPath):
(KURL::prettyURL):
(KURL::decode_string):
(escapeBadChars):
(KURL::parse):
(KURL::getNSURL):
* kwq/kdecore/kurl.h:
* khtml/khtml_part.cpp:
(KHTMLPart::end): Don't call KURL::clearCaches() any more.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@1906 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog-2002-12-03 b/WebCore/ChangeLog-2002-12-03
index b67bc9b..297cb3f 100644
--- a/WebCore/ChangeLog-2002-12-03
+++ b/WebCore/ChangeLog-2002-12-03
@@ -1,3 +1,37 @@
+2002-08-22 Maciej Stachowiak <mjs at apple.com>
+
+ Brand new KURL implementation which avoids CFURL, CFString, and
+ all that other allocation-happy goodness and instead does as much
+ work as possible with raw ASCII buffers.
+
+ For me this gave a ~5% performance improvement on cvs-base.
+
+ * kwq/KWQKURL.mm:
+ (KURL::KURL):
+ (KURL::hasPath):
+ (KURL::protocol):
+ (KURL::host):
+ (KURL::port):
+ (KURL::pass):
+ (KURL::user):
+ (KURL::ref):
+ (KURL::query):
+ (KURL::path):
+ (KURL::setProtocol):
+ (KURL::setHost):
+ (KURL::setPort):
+ (KURL::setRef):
+ (KURL::setQuery):
+ (KURL::setPath):
+ (KURL::prettyURL):
+ (KURL::decode_string):
+ (escapeBadChars):
+ (KURL::parse):
+ (KURL::getNSURL):
+ * kwq/kdecore/kurl.h:
+ * khtml/khtml_part.cpp:
+ (KHTMLPart::end): Don't call KURL::clearCaches() any more.
+
2002-08-22 Darin Adler <darin at apple.com>
* kwq/KWQButton.mm: (QButton::~QButton): Disconnect the view
diff --git a/WebCore/ChangeLog-2003-10-25 b/WebCore/ChangeLog-2003-10-25
index b67bc9b..297cb3f 100644
--- a/WebCore/ChangeLog-2003-10-25
+++ b/WebCore/ChangeLog-2003-10-25
@@ -1,3 +1,37 @@
+2002-08-22 Maciej Stachowiak <mjs at apple.com>
+
+ Brand new KURL implementation which avoids CFURL, CFString, and
+ all that other allocation-happy goodness and instead does as much
+ work as possible with raw ASCII buffers.
+
+ For me this gave a ~5% performance improvement on cvs-base.
+
+ * kwq/KWQKURL.mm:
+ (KURL::KURL):
+ (KURL::hasPath):
+ (KURL::protocol):
+ (KURL::host):
+ (KURL::port):
+ (KURL::pass):
+ (KURL::user):
+ (KURL::ref):
+ (KURL::query):
+ (KURL::path):
+ (KURL::setProtocol):
+ (KURL::setHost):
+ (KURL::setPort):
+ (KURL::setRef):
+ (KURL::setQuery):
+ (KURL::setPath):
+ (KURL::prettyURL):
+ (KURL::decode_string):
+ (escapeBadChars):
+ (KURL::parse):
+ (KURL::getNSURL):
+ * kwq/kdecore/kurl.h:
+ * khtml/khtml_part.cpp:
+ (KHTMLPart::end): Don't call KURL::clearCaches() any more.
+
2002-08-22 Darin Adler <darin at apple.com>
* kwq/KWQButton.mm: (QButton::~QButton): Disconnect the view
diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index b67bc9b..297cb3f 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,37 @@
+2002-08-22 Maciej Stachowiak <mjs at apple.com>
+
+ Brand new KURL implementation which avoids CFURL, CFString, and
+ all that other allocation-happy goodness and instead does as much
+ work as possible with raw ASCII buffers.
+
+ For me this gave a ~5% performance improvement on cvs-base.
+
+ * kwq/KWQKURL.mm:
+ (KURL::KURL):
+ (KURL::hasPath):
+ (KURL::protocol):
+ (KURL::host):
+ (KURL::port):
+ (KURL::pass):
+ (KURL::user):
+ (KURL::ref):
+ (KURL::query):
+ (KURL::path):
+ (KURL::setProtocol):
+ (KURL::setHost):
+ (KURL::setPort):
+ (KURL::setRef):
+ (KURL::setQuery):
+ (KURL::setPath):
+ (KURL::prettyURL):
+ (KURL::decode_string):
+ (escapeBadChars):
+ (KURL::parse):
+ (KURL::getNSURL):
+ * kwq/kdecore/kurl.h:
+ * khtml/khtml_part.cpp:
+ (KHTMLPart::end): Don't call KURL::clearCaches() any more.
+
2002-08-22 Darin Adler <darin at apple.com>
* kwq/KWQButton.mm: (QButton::~QButton): Disconnect the view
diff --git a/WebCore/khtml/khtml_part.cpp b/WebCore/khtml/khtml_part.cpp
index de006b2..1f4a85c 100644
--- a/WebCore/khtml/khtml_part.cpp
+++ b/WebCore/khtml/khtml_part.cpp
@@ -1451,10 +1451,6 @@ void KHTMLPart::end()
write(d->m_decoder->flush());
if (d->m_doc)
d->m_doc->finishParsing();
-
-#ifdef APPLE_CHANGES
- KURL::clearCaches();
-#endif
}
#ifndef APPLE_CHANGES
diff --git a/WebCore/kwq/KWQKURL.h b/WebCore/kwq/KWQKURL.h
index 8b2cdfc..2523ee7 100644
--- a/WebCore/kwq/KWQKURL.h
+++ b/WebCore/kwq/KWQKURL.h
@@ -43,17 +43,12 @@ public:
KURL(const KURL &, const QString &);
KURL(const QString &, int encoding_hint=0);
- KURL(const KURL &);
-
- ~KURL();
- KURL &operator=(const KURL &);
-
- bool isEmpty() const;
- bool isMalformed() const;
- bool isValid() const { return !isMalformed(); }
+ inline bool isEmpty() const { return urlString.isEmpty(); }
+ inline bool isMalformed() const { return !m_isValid; }
+ inline bool isValid() const { return m_isValid; }
bool hasPath() const;
- QString url() const;
+ inline QString url() const { return urlString; }
QString protocol() const;
QString host() const;
unsigned short int port() const;
@@ -77,22 +72,23 @@ public:
NSURL *getNSURL() const;
static QString decode_string(const QString &urlString);
- static void clearCaches();
friend bool operator==(const KURL &, const KURL &);
private:
- void swap(KURL &other);
- void copyOnWrite();
- void parse() const;
- void assemble();
- QString normalizeURLString(const QString &s);
- QString normalizeRelativeURLString(const KURL &base, const QString &relative);
-
- class KWQKURLPrivate;
+ void parse(const char *url);
- mutable KWQRefPtr<KWQKURLPrivate> d;
QString urlString;
+ bool m_isValid;
+ int schemeEndPos;
+ int userStartPos;
+ int userEndPos;
+ int passwordEndPos;
+ int hostEndPos;
+ int portEndPos;
+ int pathEndPos;
+ int queryEndPos;
+ int fragmentEndPos;
};
#endif
diff --git a/WebCore/kwq/KWQKURL.mm b/WebCore/kwq/KWQKURL.mm
index 67ab6e2..3c9df77 100644
--- a/WebCore/kwq/KWQKURL.mm
+++ b/WebCore/kwq/KWQKURL.mm
@@ -26,591 +26,555 @@
#import <kurl.h>
#import <kwqdebug.h>
-#import <Foundation/NSURLPathUtilities.h>
-class KURL::KWQKURLPrivate
-{
-public:
- KWQKURLPrivate(const QString &url);
- KWQKURLPrivate(const KWQKURLPrivate &other);
- ~KWQKURLPrivate();
-
- void makeRef();
- void decompose();
- void compose();
-
- CFURLRef urlRef;
- QString sURL;
- QString sProtocol;
- QString sHost;
- unsigned short int iPort;
- QString sPass;
- QString sUser;
- QString sRef;
- QString sQuery;
- QString sPath;
- QString escapedPath;
- bool addedSlash;
-
- int refCount;
+typedef enum {
+ // alpha
+ SchemeFirstChar = 1 << 0,
+
+ // ( alpha | digit | "+" | "-" | "." )
+ SchemeChar = 1 << 1,
+
+ // mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+ // unreserved = alphanum | mark
+ // ( unreserved | escaped | ";" | ":" | "&" | "=" | "+" | "$" | "," )
+ UserInfoChar = 1 << 2,
+
+ // alnum | "." | "-" | "%"
+ HostnameChar = 1 << 3,
+
+ // hexdigit | ":" | "%"
+ IPv6Char = 1 << 4,
+
+ // "#" | "?" | "/" | nul
+ PathSegmentEndChar = 1 << 5,
+
+ // digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f"
+ HexDigitChar = 1 << 6,
+
+ // not allowed in path and not ? or #
+ BadChar = 1 << 7
+} URLCharacterClasses;
+
+static const unsigned char characterClassTable[256] = {
+ /* 0 nul */ PathSegmentEndChar, /* 1 soh */ BadChar,
+ /* 2 stx */ BadChar, /* 3 etx */ BadChar,
+ /* 4 eot */ BadChar, /* 5 enq */ BadChar, /* 6 ack */ BadChar, /* 7 bel */ BadChar,
+ /* 8 bs */ BadChar, /* 9 ht */ BadChar, /* 10 nl */ BadChar, /* 11 vt */ BadChar,
+ /* 12 np */ BadChar, /* 13 cr */ BadChar, /* 14 so */ BadChar, /* 15 si */ BadChar,
+ /* 16 dle */ BadChar, /* 17 dc1 */ BadChar, /* 18 dc2 */ BadChar, /* 19 dc3 */ BadChar,
+ /* 20 dc4 */ BadChar, /* 21 nak */ BadChar, /* 22 syn */ BadChar, /* 23 etb */ BadChar,
+ /* 24 can */ BadChar, /* 25 em */ BadChar, /* 26 sub */ BadChar, /* 27 esc */ BadChar,
+ /* 28 fs */ BadChar, /* 29 gs */ BadChar, /* 30 rs */ BadChar, /* 31 us */ BadChar,
+ /* 32 sp */ BadChar, /* 33 ! */ UserInfoChar,
+ /* 34 " */ BadChar, /* 35 # */ PathSegmentEndChar,
+ /* 36 $ */ UserInfoChar, /* 37 % */ UserInfoChar | HostnameChar | IPv6Char | BadChar,
+ /* 38 & */ UserInfoChar, /* 39 ' */ UserInfoChar,
+ /* 40 ( */ UserInfoChar, /* 41 ) */ UserInfoChar,
+ /* 42 * */ UserInfoChar, /* 43 + */ SchemeChar | UserInfoChar,
+ /* 44 , */ UserInfoChar,
+ /* 45 - */ SchemeChar | UserInfoChar | HostnameChar,
+ /* 46 . */ SchemeChar | UserInfoChar | HostnameChar,
+ /* 47 / */ PathSegmentEndChar,
+ /* 48 0 */ SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 49 1 */ SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 50 2 */ SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 51 3 */ SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 52 4 */ SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 53 5 */ SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 54 6 */ SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 55 7 */ SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 56 8 */ SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 57 9 */ SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 58 : */ UserInfoChar | IPv6Char, /* 59 ; */ UserInfoChar,
+ /* 60 < */ BadChar, /* 61 = */ UserInfoChar,
+ /* 62 > */ BadChar, /* 63 ? */ PathSegmentEndChar,
+ /* 64 @ */ 0,
+ /* 65 A */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 66 B */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 67 C */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 68 D */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 69 E */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 70 F */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 71 G */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 72 H */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 73 I */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 74 J */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 75 K */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 76 L */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 77 M */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 78 N */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 79 O */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 80 P */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 81 Q */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 82 R */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 83 S */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 84 T */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 85 U */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 86 V */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 87 W */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 88 X */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 89 Y */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 90 Z */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 91 [ */ BadChar,
+ /* 92 \ */ BadChar, /* 93 ] */ BadChar,
+ /* 94 ^ */ BadChar, /* 95 _ */ UserInfoChar,
+ /* 96 ` */ BadChar,
+ /* 97 a */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 98 b */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 99 c */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 100 d */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 101 e */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 102 f */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar | HexDigitChar | IPv6Char,
+ /* 103 g */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 104 h */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 105 i */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 106 j */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 107 k */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 108 l */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 109 m */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 110 n */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 111 o */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 112 p */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 113 q */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 114 r */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 115 s */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 116 t */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 117 u */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 118 v */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 119 w */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 120 x */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 121 y */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 122 z */ SchemeFirstChar | SchemeChar | UserInfoChar | HostnameChar,
+ /* 123 { */ BadChar,
+ /* 124 | */ BadChar, /* 125 } */ BadChar, /* 126 ~ */ UserInfoChar, /* 127 del */ BadChar,
+ /* 128 */ BadChar, /* 129 */ BadChar, /* 130 */ BadChar, /* 131 */ BadChar,
+ /* 132 */ BadChar, /* 133 */ BadChar, /* 134 */ BadChar, /* 135 */ BadChar,
+ /* 136 */ BadChar, /* 137 */ BadChar, /* 138 */ BadChar, /* 139 */ BadChar,
+ /* 140 */ BadChar, /* 141 */ BadChar, /* 142 */ BadChar, /* 143 */ BadChar,
+ /* 144 */ BadChar, /* 145 */ BadChar, /* 146 */ BadChar, /* 147 */ BadChar,
+ /* 148 */ BadChar, /* 149 */ BadChar, /* 150 */ BadChar, /* 151 */ BadChar,
+ /* 152 */ BadChar, /* 153 */ BadChar, /* 154 */ BadChar, /* 155 */ BadChar,
+ /* 156 */ BadChar, /* 157 */ BadChar, /* 158 */ BadChar, /* 159 */ BadChar,
+ /* 160 */ BadChar, /* 161 */ BadChar, /* 162 */ BadChar, /* 163 */ BadChar,
+ /* 164 */ BadChar, /* 165 */ BadChar, /* 166 */ BadChar, /* 167 */ BadChar,
+ /* 168 */ BadChar, /* 169 */ BadChar, /* 170 */ BadChar, /* 171 */ BadChar,
+ /* 172 */ BadChar, /* 173 */ BadChar, /* 174 */ BadChar, /* 175 */ BadChar,
+ /* 176 */ BadChar, /* 177 */ BadChar, /* 178 */ BadChar, /* 179 */ BadChar,
+ /* 180 */ BadChar, /* 181 */ BadChar, /* 182 */ BadChar, /* 183 */ BadChar,
+ /* 184 */ BadChar, /* 185 */ BadChar, /* 186 */ BadChar, /* 187 */ BadChar,
+ /* 188 */ BadChar, /* 189 */ BadChar, /* 190 */ BadChar, /* 191 */ BadChar,
+ /* 192 */ BadChar, /* 193 */ BadChar, /* 194 */ BadChar, /* 195 */ BadChar,
+ /* 196 */ BadChar, /* 197 */ BadChar, /* 198 */ BadChar, /* 199 */ BadChar,
+ /* 200 */ BadChar, /* 201 */ BadChar, /* 202 */ BadChar, /* 203 */ BadChar,
+ /* 204 */ BadChar, /* 205 */ BadChar, /* 206 */ BadChar, /* 207 */ BadChar,
+ /* 208 */ BadChar, /* 209 */ BadChar, /* 210 */ BadChar, /* 211 */ BadChar,
+ /* 212 */ BadChar, /* 213 */ BadChar, /* 214 */ BadChar, /* 215 */ BadChar,
+ /* 216 */ BadChar, /* 217 */ BadChar, /* 218 */ BadChar, /* 219 */ BadChar,
+ /* 220 */ BadChar, /* 221 */ BadChar, /* 222 */ BadChar, /* 223 */ BadChar,
+ /* 224 */ BadChar, /* 225 */ BadChar, /* 226 */ BadChar, /* 227 */ BadChar,
+ /* 228 */ BadChar, /* 229 */ BadChar, /* 230 */ BadChar, /* 231 */ BadChar,
+ /* 232 */ BadChar, /* 233 */ BadChar, /* 234 */ BadChar, /* 235 */ BadChar,
+ /* 236 */ BadChar, /* 237 */ BadChar, /* 238 */ BadChar, /* 239 */ BadChar,
+ /* 240 */ BadChar, /* 241 */ BadChar, /* 242 */ BadChar, /* 243 */ BadChar,
+ /* 244 */ BadChar, /* 245 */ BadChar, /* 246 */ BadChar, /* 247 */ BadChar,
+ /* 248 */ BadChar, /* 249 */ BadChar, /* 250 */ BadChar, /* 251 */ BadChar,
+ /* 252 */ BadChar, /* 253 */ BadChar, /* 254 */ BadChar, /* 255 */ BadChar
};
+// FIXME: convert to inline functions
-KURL::KWQKURLPrivate::KWQKURLPrivate(const QString &url) :
- urlRef(NULL),
- sURL(url),
- iPort(0),
- addedSlash(false),
- refCount(0)
-{
- decompose();
-}
+#define IS_SCHEME_FIRST_CHAR(c) (characterClassTable[(unsigned char)c] & SchemeFirstChar)
+#define IS_SCHEME_CHAR(c) (characterClassTable[(unsigned char)c] & SchemeChar)
+#define IS_USERINFO_CHAR(c) (characterClassTable[(unsigned char)c] & UserInfoChar)
+#define IS_HOSTNAME_CHAR(c) (characterClassTable[(unsigned char)c] & HostnameChar)
+#define IS_IPV6_CHAR(c) (characterClassTable[(unsigned char)c] & IPv6Char)
+#define IS_PATH_SEGMENT_END_CHAR(c) (characterClassTable[(unsigned char)c] & PathSegmentEndChar)
+#define IS_BAD_CHAR(c) (characterClassTable[(unsigned char)c] & BadChar)
+#define IS_HEX_DIGIT(c) (characterClassTable[(unsigned char)c] & HexDigitChar)
-KURL::KWQKURLPrivate::KWQKURLPrivate(const KWQKURLPrivate &other) :
- urlRef(other.urlRef != NULL ? (CFURLRef)CFRetain(other.urlRef) : NULL),
- sURL(other.sURL),
- sProtocol(other.sProtocol),
- sHost(other.sHost),
- iPort(other.iPort),
- sPass(other.sPass),
- sUser(other.sUser),
- sRef(other.sRef),
- sQuery(other.sQuery),
- sPath(other.sPath),
- escapedPath(other.escapedPath),
- addedSlash(other.addedSlash),
- refCount(0)
-{
-}
-KURL::KWQKURLPrivate::~KWQKURLPrivate()
-{
- if (urlRef != NULL) {
- CFRelease(urlRef);
- }
-}
+// KURL
-void KURL::KWQKURLPrivate::makeRef()
+KURL::KURL() :
+ m_isValid(false)
{
- // Not a path and no scheme, so bail out, because CFURL considers such
- // things valid URLs for some reason.
- if (!sURL.contains(':') && (sURL.length() == 0 || sURL[0] != '/') || sURL == "file:" || sURL == "file://") {
- urlRef = NULL;
- return;
- }
-
- // Create CFURLRef object
- if (sURL.length() > 0 && sURL[0] == '/') {
- sURL = "file://" + sURL;
- } else if (sURL.startsWith("file:/") && !sURL.startsWith("file://")) {
- sURL = "file:///" + sURL.mid(6);
- }
-
- QString sURLMaybeAddSlash;
- int colonPos = sURL.find(':');
- int slashSlashPos = sURL.find("//", colonPos);
- if (slashSlashPos != -1 && sURL.find('/', slashSlashPos + 2) == -1) {
- sURLMaybeAddSlash = sURL + "/";
- addedSlash = true;
- } else {
- sURLMaybeAddSlash = sURL;
- addedSlash = false;
- }
-
- // Escape illegal but unambiguous characters that are actually
- // found on the web in URLs, like ' ' or '|'
- CFStringRef escaped = CFURLCreateStringByAddingPercentEscapes(NULL, sURLMaybeAddSlash.getCFString(),
- CFSTR("%#"), NULL, kCFStringEncodingUTF8);
-
- urlRef = CFURLCreateWithString(NULL, escaped, NULL);
-
- CFRelease(escaped);
}
-static inline QString CFStringToQString(CFStringRef cfs)
+KURL::KURL(const char *url, int encoding_hint) :
+ m_isValid(true)
{
- QString qs;
-
- if (cfs != NULL) {
- qs = QString::fromCFString(cfs);
- CFRelease(cfs);
+ if (url != NULL && url[0] == '/') {
+ QString qurl = QString("file:") + url;
+ parse(qurl.ascii());
} else {
- qs = QString();
+ parse(url);
}
-
- return qs;
}
-static inline QString escapeQString(const QString &str)
-{
- return CFStringToQString(CFURLCreateStringByAddingPercentEscapes(NULL, str.getCFString(), NULL, NULL, kCFStringEncodingUTF8));
-}
+KURL::KURL(const QString &url, int encoding_hint) :
+ m_isValid(true)
-static bool pathEndsWithSlash(const QString &sURL)
{
- int endOfPath = sURL.findRev('?', sURL.findRev('#'));
- if (endOfPath == -1) {
- endOfPath = sURL.length();
- }
- if (sURL[endOfPath-1] == '/') {
- return true;
+ if (!url.isEmpty() && url[0] == '/') {
+ QString fileUrl = QString("file:") + url;
+ parse(fileUrl.ascii());
} else {
- return false;
+ parse(url.ascii());
}
}
-void KURL::KWQKURLPrivate::decompose()
+KURL::KURL(const KURL &base, const QString &relative)
{
- makeRef();
-
- if (urlRef == NULL) {
- // failed to parse
- return;
- }
-
- // decompose into parts
-
- sProtocol = CFStringToQString(CFURLCopyScheme(urlRef));
-
- QString hostName = CFStringToQString(CFURLCopyHostName(urlRef));
- if (sProtocol != "file") {
- sHost = hostName;
+ bool absolute = false;
+ const char *str = relative.ascii();
+ for (const char *p = str; *p != '\0'; ++p) {
+ if (*p == ':') {
+ absolute = true;
+ break;
+ } else if (*p == '/' || *p == '?' || *p == '#') {
+ break;
+ }
}
-
- SInt32 portNumber = CFURLGetPortNumber(urlRef);
- if (portNumber < 0) {
- iPort = 0;
+
+ if (absolute) {
+ parse(str);
} else {
- iPort = portNumber;
- }
-
- sPass = CFStringToQString(CFURLCopyPassword(urlRef));
- sUser = CFStringToQString(CFURLCopyUserName(urlRef));
- sRef = CFStringToQString(CFURLCopyFragment(urlRef, NULL));
-
- sQuery = CFStringToQString(CFURLCopyQueryString(urlRef, NULL));
- if (!sQuery.isEmpty()) {
- sQuery = "?" + sQuery;
- }
-
- if (CFURLCanBeDecomposed(urlRef)) {
- if (addedSlash) {
- sPath = "";
- escapedPath = "";
- } else {
- sPath = CFStringToQString(CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle));
- escapedPath = CFStringToQString(CFURLCopyPath(urlRef));
- }
-
- // Remove "../" or "./" from the start of the path.
- // This is not what RFC 2396 says to do, but it's what other browsers do.
- if (sPath.startsWith("/.")) {
- for (;;) {
- if (sPath.startsWith("/./")) {
- sPath.remove(0, 2);
- } else if (sPath.startsWith("/../")) {
- sPath.remove(0, 3);
- } else {
- break;
- }
- }
- for (;;) {
- if (escapedPath.startsWith("/./")) {
- escapedPath.remove(0, 2);
- } else if (escapedPath.startsWith("/../")) {
- escapedPath.remove(0, 3);
- } else {
- break;
- }
- }
- }
-
- QString param = CFStringToQString(CFURLCopyParameterString(urlRef, CFSTR("")));
- if (!param.isEmpty()) {
- sPath += ";" + param;
- escapedPath += ";" + CFStringToQString(CFURLCopyParameterString(urlRef, NULL));
+ // workaround for sites that put leading whitespace on relative URLs
+ while (*str == ' ') {
+ str++;
}
- if (pathEndsWithSlash(sURL) && sPath.right(1) != "/") {
- sPath += "/";
+ if (!base.m_isValid) {
+ QString newURL = base.urlString + relative;
+ parse(newURL.ascii());
}
- } else {
- sPath = CFStringToQString(CFURLCopyResourceSpecifier(urlRef));
- escapedPath = sPath;
- }
-
- if (sProtocol == "file" && !hostName.isEmpty() && hostName != "localhost") {
- sPath = "//" + hostName + sPath;
- escapedPath = "//" + hostName + escapedPath;
- }
- // could lead to poor performance - perhaps compose manually in ::url?
- if (sURL != "file://localhost") {
- compose();
- }
-}
-
-void KURL::KWQKURLPrivate::compose()
-{
- if (!sProtocol.isEmpty()) {
- QString result = escapeQString(sProtocol) + ":";
-
- if (!sHost.isEmpty()) {
- result += "//";
- if (!sUser.isEmpty()) {
- result += escapeQString(sUser);
- if (!sPass.isEmpty()) {
- result += ":" + escapeQString(sPass);
- }
- result += "@";
+ switch(str[0]) {
+ case '\0':
+ // empty
+ {
+ *this = base;
+ break;
}
- result += escapeQString(sHost);
- if (iPort != 0) {
- result += ":" + QString::number(iPort);
+ case '#':
+ // must be fragment reference only
+ {
+ QString newURL = base.urlString.left(base.queryEndPos) + relative;
+ parse(newURL.ascii());
+ break;
}
- }
+ case '/':
+ // must be net-path or absolute-path reference
+ {
+ if (str[1] == '/') {
+ // net-path
+ QString newURL = base.urlString.left(base.schemeEndPos + 1) + str;
+ parse(newURL.ascii());
+ } else {
+ // abs-path
+ QString newURL = base.urlString.left(base.portEndPos) + str;
+ parse(newURL.ascii());
+ }
+ break;
+ }
+ default:
+ {
+ // must be relative-path reference
+ QString newURL = base.urlString.left(base.portEndPos);
+ char static_buffer[2048];
+ char *buffer;
+ bool usingStaticBuffer;
+
+ if ((base.pathEndPos - base.portEndPos) + relative.length() >= 2048) {
+ buffer = (char *)malloc(((base.pathEndPos - base.portEndPos) + relative.length() + 1) * sizeof(char));
+ usingStaticBuffer = false;
+ } else {
+ buffer = static_buffer;
+ usingStaticBuffer = true;
+ }
+
+ char *bufferPos = buffer;
+
+ // first copy the base path
+ const char *baseString = base.urlString.ascii();
+ const char *baseStringStart = baseString + base.portEndPos;
+ const char *baseStringEnd = baseString + base.pathEndPos;
+
+ // go back to the last slash
+ while (baseStringEnd > baseStringStart && baseStringEnd[-1] != '/') {
+ baseStringEnd--;
+ }
+
+ // now copy the base path, accounting for "." and ".." segments
+ const char *baseStringPos = baseStringStart;
+ while (baseStringPos < baseStringEnd) {
+ if (baseStringPos[0] == '.' && bufferPos[-1] == '/') {
+ if (baseStringPos[1] == '/' || baseStringPos + 1 == baseStringEnd) {
+ // skip over "." segments
+ baseStringPos += 2;
+ continue;
+ } else if (baseStringPos[1] == '.' && (baseStringPos[2] == '/' ||
+ baseStringPos + 2 == baseStringEnd)) {
+ // skip over ".." segments and rewind the last segment
+ baseStringPos += 3;
+ if (bufferPos > buffer + 1) {
+ bufferPos--;
+ }
+ while (bufferPos > buffer && bufferPos[-1] != '/') {
+ bufferPos--;
+ }
+ // don't strip the slash before the last path segment if it was the final one
+ if (baseStringPos[2] != '/') {
+ bufferPos++;
+ }
+ continue;
+ }
+ }
+
+ *bufferPos = *baseStringPos;
+ baseStringPos++;
+ bufferPos++;
+ }
- result += escapedPath + sQuery;
-
- if (!sRef.isEmpty()) {
- result += "#" + sRef;
- }
+ const char *relStringStart = relative.ascii();
+ const char *relStringPos = relStringStart;
+
+ while (*relStringPos != '\0' && *relStringPos != '?' && *relStringPos != '#') {
+ if (relStringPos[0] == '.' && bufferPos[-1] == '/') {
+ if (IS_PATH_SEGMENT_END_CHAR(relStringPos[1])) {
+ // skip over "." segments
+ relStringPos += 1;
+ if (relStringPos[0] == '/') {
+ relStringPos++;
+ }
+ continue;
+ } else if (relStringPos[1] == '.' && IS_PATH_SEGMENT_END_CHAR(relStringPos[2])) {
+ // skip over ".." segments and rewind the last segment
+ relStringPos += 2;
+ if (relStringPos[0] == '/') {
+ relStringPos++;
+ }
+ if (bufferPos > buffer + 1) {
+ bufferPos--;
+ }
+ while (bufferPos > buffer + 1 && bufferPos[-1] != '/') {
+ bufferPos--;
+ }
+ continue;
+ }
+ }
+
+ *bufferPos = *relStringPos;
+ relStringPos++;
+ bufferPos++;
+ }
- if (urlRef != NULL) {
- CFRelease(urlRef);
- urlRef = NULL;
+ // all done with the path work, now copy any remainder
+ // of the relative reference; this will also add a null terminator
+ strcpy(bufferPos, relStringPos);
+
+ // and parse the thing (throwing away the fact that we
+ // know the path bounds already, but what the heck)
+ newURL += buffer;
+
+ parse(newURL.ascii());
+
+ if (!usingStaticBuffer) {
+ free(buffer);
+ }
+
+ break;
+ }
}
-
- sURL = result;
-
- makeRef();
}
}
-struct RelativeURLKey {
- CFStringRef base;
- CFStringRef relative;
- int refCount;
-};
-
-static const void *RelativeURLKeyRetainCallBack(CFAllocatorRef allocator, const void *value)
-{
- RelativeURLKey *key = (RelativeURLKey *)value;
- CFRetain(key->base);
- CFRetain(key->relative);
- ++key->refCount;
- return key;
-}
-
-static void RelativeURLKeyReleaseCallBack(CFAllocatorRef allocator, const void *value)
-{
- RelativeURLKey *key = (RelativeURLKey *)value;
- CFRelease(key->base);
- CFRelease(key->relative);
- if (--key->refCount == 0)
- delete key;
-}
-
-static CFStringRef RelativeURLKeyCopyDescriptionCallBack(const void *value)
+bool KURL::hasPath() const
{
- return CFSTR("");
+ return m_isValid && pathEndPos != portEndPos;
}
-static unsigned char RelativeURLKeyEqualCallBack(const void *value1, const void *value2)
+QString KURL::protocol() const
{
- RelativeURLKey *key1 = (RelativeURLKey *)value1;
- RelativeURLKey *key2 = (RelativeURLKey *)value2;
-
- return CFEqual(key1->base, key2->base) && CFEqual(key1->relative, key2->relative);
-}
+ if (!m_isValid) {
+ return QString();
+ }
-static CFHashCode RelativeURLKeyHashCallBack(const void *value)
-{
- RelativeURLKey *key = (RelativeURLKey *)value;
- return CFHash(key->base) ^ CFHash(key->relative);
+ return urlString.left(schemeEndPos);
}
-static const CFDictionaryKeyCallBacks RelativeURLKeyCallBacks = {
- 0,
- RelativeURLKeyRetainCallBack,
- RelativeURLKeyReleaseCallBack,
- RelativeURLKeyCopyDescriptionCallBack,
- RelativeURLKeyEqualCallBack,
- RelativeURLKeyHashCallBack,
-};
-
-
-static CFMutableDictionaryRef NormalizedURLCache = NULL;
-static CFMutableDictionaryRef NormalizedRelativeURLCache = NULL;
-
-void KURL::clearCaches()
+QString KURL::host() const
{
- if (NormalizedURLCache != NULL) {
- CFDictionaryRemoveAllValues(NormalizedURLCache);
- }
- if (NormalizedRelativeURLCache != NULL) {
- CFDictionaryRemoveAllValues(NormalizedRelativeURLCache);
+ if (!m_isValid) {
+ return QString();
}
+
+ int start = (passwordEndPos == userStartPos) ? passwordEndPos : passwordEndPos + 1;
+ return decode_string(urlString.mid(start, hostEndPos - start));
}
-QString KURL::normalizeURLString(const QString &s)
+unsigned short int KURL::port() const
{
- if (NormalizedURLCache == NULL) {
- NormalizedURLCache = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (!m_isValid) {
+ return 0;
}
- CFStringRef result = (CFStringRef)CFDictionaryGetValue(NormalizedURLCache, s.getCFString());
- if (result != NULL) {
- return QString::fromCFString(result);
- }
-
- // normalize the URL string as KURL would:
-
- QString qurl = s;
-
- // Special handling for paths
- if (!qurl.isEmpty() && qurl[0] == '/') {
- qurl = "file:" + qurl;
- }
-
- // FIXME: Do we really have to parse even the simplest URLs into pieces just to normalize them?
- if (d.isNull()) {
- d = KWQRefPtr<KWQKURLPrivate>(new KWQKURLPrivate(qurl));
- }
-
- qurl = d->sURL;
-
- if (qurl.startsWith("file:///")) {
- qurl = "file:/" + qurl.mid(8);
- } else if (qurl == "file://localhost") {
- qurl = "file:";
- } else if (qurl.startsWith("file://localhost/")) {
- qurl = "file:/" + qurl.mid(17);
+ if (hostEndPos != portEndPos) {
+ bool ok;
+ unsigned short result = urlString.mid(hostEndPos + 1, portEndPos - hostEndPos - 1).toUShort(&ok);
+ if (!ok) {
+ result = 0;
+ }
+ return result;
}
- CFDictionarySetValue(NormalizedURLCache, s.getCFString(), qurl.getCFString());
-
- return qurl;
+ return 0;
}
-QString KURL::normalizeRelativeURLString(const KURL &base, const QString &relative)
+QString KURL::pass() const
{
- if (NormalizedRelativeURLCache == NULL) {
- NormalizedRelativeURLCache = CFDictionaryCreateMutable(NULL, 0, &RelativeURLKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- }
-
- RelativeURLKey key = { base.urlString.getCFString(), relative.getCFString(), 0 };
- CFStringRef cachedResult = (CFMutableStringRef)CFDictionaryGetValue(NormalizedRelativeURLCache, &key);
- if (cachedResult != NULL) {
- return QString::fromCFString(cachedResult);
+ if (!m_isValid) {
+ return QString();
}
-
- QString stripped = relative.stripWhiteSpace();
- QString result;
- if (stripped.isEmpty()) {
- result = base.urlString;
- } else {
- base.parse();
-
- CFStringRef relativeURLString = CFURLCreateStringByAddingPercentEscapes
- (NULL, stripped.getCFString(), CFSTR("%#"), NULL, kCFStringEncodingUTF8);
-
- CFURLRef relativeURL = CFURLCreateWithString(NULL, relativeURLString, base.d->urlRef);
- CFRelease(relativeURLString);
-
- if (relativeURL == NULL) {
- result = normalizeURLString(stripped);
- } else {
- CFURLRef absoluteURL = CFURLCopyAbsoluteURL(relativeURL);
-
- result = normalizeURLString(QString::fromCFString(CFURLGetString(absoluteURL)));
-
- CFRelease(relativeURL);
- CFRelease(absoluteURL);
- }
+ if (passwordEndPos == userEndPos) {
+ return QString();
}
-
- CFDictionarySetValue(NormalizedRelativeURLCache, new RelativeURLKey(key), result.getCFString());
- return result;
-}
-
-// KURL
-
-KURL::KURL() :
- d(NULL)
-{
-}
-
-KURL::KURL(const char *url, int encoding_hint) :
- d(NULL),
- urlString(normalizeURLString(url))
-{
-}
-
-KURL::KURL(const QString &url, int encoding_hint) :
- d(NULL),
- urlString(normalizeURLString(url))
-{
-}
-
-KURL::KURL(const KURL &base, const QString &relative) :
- d(NULL),
- urlString(normalizeRelativeURLString(base, relative))
-{
-}
-
-KURL::KURL(const KURL &other) :
- d(other.d),
- urlString(other.urlString)
-{
-}
-
-KURL::~KURL()
-{
-}
-
-bool KURL::isEmpty() const
-{
- parse();
- return d->sURL.isEmpty();
-}
-
-bool KURL::isMalformed() const
-{
- parse();
- return (d->urlRef == NULL);
-}
-
-bool KURL::hasPath() const
-{
- parse();
- return !d->sPath.isEmpty();
-}
-QString KURL::url() const
-{
- return urlString;
-}
-
-QString KURL::protocol() const
-{
- parse();
- return d->sProtocol;
-}
-
-QString KURL::host() const
-{
- parse();
- return d->sHost;
-}
-
-unsigned short int KURL::port() const
-{
- parse();
- return d->iPort;
-}
-
-QString KURL::pass() const
-{
- parse();
- return d->sPass;
+ return decode_string(urlString.mid(userEndPos + 1, passwordEndPos - userEndPos - 1));
}
QString KURL::user() const
{
- parse();
- return d->sUser;
+ if (!m_isValid) {
+ return QString();
+ }
+
+ return decode_string(urlString.mid(userStartPos, userEndPos - userStartPos));
}
QString KURL::ref() const
{
- parse();
- return d->sRef;
+ if (!m_isValid) {
+ return QString();
+ }
+
+ if (fragmentEndPos == queryEndPos) {
+ return QString();
+ }
+
+ return urlString.mid(queryEndPos + 1, fragmentEndPos - queryEndPos - 1);
}
QString KURL::query() const
{
- parse();
- return d->sQuery;
+ if (!m_isValid) {
+ return QString();
+ }
+
+ return urlString.mid(pathEndPos, queryEndPos - pathEndPos);
}
QString KURL::path() const
{
- parse();
- return d->sPath;
+ if (!m_isValid) {
+ return QString();
+ }
+
+ return decode_string(urlString.mid(portEndPos, pathEndPos - portEndPos));
}
void KURL::setProtocol(const QString &s)
{
- copyOnWrite();
- d->sProtocol = s;
- assemble();
+ if (!m_isValid) {
+ QString newURL = s + ":" + urlString;
+ parse(newURL.ascii());
+ return;
+ }
+
+ QString newURL = s + urlString.mid(schemeEndPos);
+ parse(newURL.ascii());
}
void KURL::setHost(const QString &s)
{
- copyOnWrite();
- d->sHost = s;
- assemble();
+ if (m_isValid) {
+ bool slashSlashNeeded = userStartPos == schemeEndPos + 1;
+ int hostStart = (passwordEndPos == userStartPos) ? passwordEndPos : passwordEndPos + 1;
+
+ QString newURL = urlString.left(hostStart) + (slashSlashNeeded ? "//" : QString()) + s + urlString.mid(hostEndPos);
+ parse(newURL.ascii());
+ }
}
void KURL::setPort(unsigned short i)
{
- copyOnWrite();
- d->iPort = i;
- assemble();
+ if (m_isValid) {
+ bool colonNeeded = portEndPos == hostEndPos;
+ int portStart = (colonNeeded ? hostEndPos : hostEndPos + 1);
+ QString newURL = urlString.left(portStart) + (colonNeeded ? ":" : QString()) + QString::number(i) + urlString.mid(portEndPos);
+ parse(newURL.ascii());
+ }
}
void KURL::setRef(const QString &s)
{
- copyOnWrite();
- d->sRef = s;
- assemble();
+ if (m_isValid) {
+ QString newURL = urlString.left(queryEndPos) + (s.isEmpty() ? QString() : "#" + s);
+ parse(newURL.ascii());
+ }
}
void KURL::setQuery(const QString &query, int encoding_hint)
{
- copyOnWrite();
- if (query.isEmpty() || query[0] == '?') {
- d->sQuery = query;
- } else {
- d->sQuery = "?" + query;
+ QString q;
+ if (m_isValid) {
+ if (!query.isEmpty() && query[0] != '?') {
+ q = "?" + query;
+ } else {
+ q = query;
+ }
+
+ QString newURL = urlString.left(pathEndPos) + q + urlString.mid(queryEndPos);
+ parse(newURL.ascii());
}
- assemble();
}
void KURL::setPath(const QString &s)
{
- copyOnWrite();
- d->sPath = s;
- d->escapedPath = escapeQString(s);
- assemble();
+ if (m_isValid) {
+ QString newURL = urlString.left(portEndPos) + s + urlString.mid(pathEndPos);
+ parse(newURL.ascii());
+ }
}
QString KURL::prettyURL(int trailing) const
{
- parse();
- if (d->urlRef == NULL) {
- return d->sURL;
+ if (!m_isValid) {
+ return urlString;
}
- QString result = d->sProtocol + ":";
+ QString result = protocol() + ":";
- if (!d->sHost.isEmpty()) {
- result += "//";
- if (!d->sUser.isEmpty()) {
- result += d->sUser;
- result += "@";
+ QString authority;
+
+ if (hostEndPos != passwordEndPos) {
+ if (userEndPos != userStartPos) {
+ authority += user();
+ authority += "@";
}
- result += d->sHost;
- if (d->iPort != 0) {
- result += ":";
- result += QString::number(d->iPort);
+ authority += host();
+ if (port() != 0) {
+ authority += ":";
+ authority += QString::number(port());
}
}
- QString path = d->sPath;
+ if (!authority.isEmpty()) {
+ result += "//" + authority;
+ }
+
+ QString path = this->path();
if (trailing == 1) {
if (path.right(1) != "/" && !path.isEmpty()) {
@@ -623,35 +587,19 @@ QString KURL::prettyURL(int trailing) const
}
result += path;
- result += d->sQuery;
+ result += query();
- if (!d->sRef.isEmpty()) {
- result += "#" + d->sRef;
+ if (fragmentEndPos != queryEndPos) {
+ result += "#" + ref();
}
return result;
}
-
-void KURL::swap(KURL &other)
-{
- KWQRefPtr<KWQKURLPrivate> tmpD = other.d;
- QString tmpString = other.urlString;
- other.d = d;
- d = tmpD;
- other.urlString = urlString;
- urlString = tmpString;
-}
-
-
-KURL &KURL::operator=(const KURL &other)
-{
- KURL(other).swap(*this);
- return *this;
-}
-
QString KURL::decode_string(const QString &urlString)
{
+ // FIXME: do it yerself
+
CFStringRef unescaped = CFURLCreateStringByReplacingPercentEscapes(NULL, urlString.getCFString(), CFSTR(""));
QString qUnescaped = QString::fromCFString(unescaped);
CFRelease(unescaped);
@@ -659,33 +607,285 @@ QString KURL::decode_string(const QString &urlString)
return qUnescaped;
}
-void KURL::copyOnWrite()
+const char *hexDigits="0123456789ABCDEF";
+
+static QString escapeBadChars(const QString &strToEscape)
{
- parse();
- if (d->refCount > 1) {
- d = KWQRefPtr<KWQKURLPrivate>(new KWQKURLPrivate(*d));
+ const char *str = strToEscape.ascii();
+ char static_buffer[4096];
+ bool usingStaticBuffer;
+ char *buffer;
+
+ if (strToEscape.length() * 3 < 4096) {
+ buffer = static_buffer;
+ usingStaticBuffer = true;
+ } else {
+ buffer = (char *)malloc((strToEscape.length() * 3 + 1) * sizeof(char));
+ usingStaticBuffer = false;
+ }
+
+ char *p = buffer;
+
+ while (*str != '\0') {
+ if (*str == '%' && IS_HEX_DIGIT(str[1]) && IS_HEX_DIGIT(str[2])) {
+ *p++ = *str++;
+ *p++ = *str++;
+ *p++ = *str++;
+ } else if (IS_BAD_CHAR(*str)) {
+ *p++ = '%';
+ *p++ = hexDigits[(*str) / 16];
+ *p++ = hexDigits[(*str) % 16];
+ str++;
+ } else {
+ *p++ = *str++;
+ }
+ }
+ *p = '\0';
+
+ QString result(buffer);
+ if (!usingStaticBuffer) {
+ free(buffer);
}
+
+ return result;
}
-void KURL::parse() const
+
+
+void KURL::parse(const char *url)
{
- if (d.isNull()) {
- d = KWQRefPtr<KWQKURLPrivate>(new KWQKURLPrivate(urlString));
+ m_isValid = true;
+
+ if (url == NULL || url[0] == '\0') {
+ // valid URL must be non-empty
+ m_isValid = false;
+ urlString = url;
+ return;
}
-}
-void KURL::assemble()
-{
- if (!d.isNull()) {
- d->compose();
- urlString = d->sURL;
+ if (!IS_SCHEME_FIRST_CHAR(url[0])) {
+ // scheme must start with an alphabetic character
+ m_isValid = false;
+ urlString = url;
+ return;
+ }
+
+ int schemeEnd = 0;
+
+ while (IS_SCHEME_CHAR(url[schemeEnd])) {
+ schemeEnd++;
+ }
+
+ if (url[schemeEnd] != ':') {
+ m_isValid = false;
+ urlString = url;
+ return;
+ }
+
+ int userStart = schemeEnd + 1;
+ int userEnd;
+ int passwordStart;
+ int passwordEnd;
+ int hostStart;
+ int hostEnd;
+ int portStart;
+ int portEnd;
+
+ bool hierarchical = url[schemeEnd + 1] == '/';
+
+ if (hierarchical && url[schemeEnd + 2] == '/') {
+ // part after the scheme must be a net_path, parse the authority section
+
+ // FIXME: authority characters may be scanned twice
+ userStart += 2;
+ userEnd = userStart;
+
+ int colonPos = 0;
+ while (IS_USERINFO_CHAR(url[userEnd])) {
+ if (url[userEnd] == ':' && colonPos == 0) {
+ colonPos = userEnd;
+ }
+ userEnd++;
+ }
+
+ if (url[userEnd] == '@') {
+ // actual end of the userinfo, start on the host
+ if (colonPos != 0) {
+ passwordEnd = userEnd;
+ userEnd = colonPos;
+ passwordStart = colonPos + 1;
+ } else {
+ passwordStart = passwordEnd = userEnd;
+ }
+ hostStart = passwordEnd + 1;
+ } else if (url[userEnd] == '\0' || url[userEnd] == '/' || url[userEnd] == '[') {
+ // hit the end of the authority, must have been no user
+ // or looks like an IPv6 hostname
+ // either way, try to parse it as a hostname
+ userEnd = userStart;
+ passwordStart = passwordEnd = userEnd;
+ hostStart = userStart;
+ } else {
+ // invalid character
+ m_isValid = false;
+ urlString = url;
+ return;
+ }
+
+ hostEnd = hostStart;
+
+ // IPV6 IP address
+ if (url[hostEnd] == '[') {
+ hostEnd++;
+ while (IS_IPV6_CHAR(url[hostEnd])) {
+ hostEnd++;
+ }
+ if (url[hostEnd] == ']') {
+ hostEnd++;
+ } else {
+ // invalid character
+ m_isValid = false;
+ urlString = url;
+ return;
+ }
+ } else {
+ while (IS_HOSTNAME_CHAR(url[hostEnd])) {
+ hostEnd++;
+ }
+ }
+
+ if (url[hostEnd] == ':') {
+ portStart = portEnd = hostEnd + 1;
+
+ // possible start of port
+ portEnd = portStart;
+ while (isdigit(url[portEnd])) {
+ portEnd++;
+ }
+ } else {
+ portStart = portEnd = hostEnd;
+ }
+
+ if (url[portEnd] != '\0' && url[portEnd] != '/') {
+ // invalid character
+ m_isValid = false;
+ urlString = url;
+ return;
+ }
+ } else {
+ // the part after the scheme must be an opaque_part or an abs_path
+ userEnd = userStart;
+ passwordStart = passwordEnd = userEnd;
+ hostStart = hostEnd = passwordEnd;
+ portStart = portEnd = hostEnd;
+ }
+
+ int pathStart = portEnd;
+ int pathEnd;
+ int queryStart;
+ int queryEnd;
+ int fragmentStart;
+ int fragmentEnd;
+
+ if (!hierarchical) {
+ // FIXME: could have a fragment
+ pathEnd = strlen(url);
+ queryStart = queryEnd = pathEnd;
+ fragmentStart = fragmentEnd = queryEnd;
+ } else {
+ pathEnd = pathStart;
+ while (url[pathEnd] != '\0' && url[pathEnd] != '?' && url[pathEnd] != '#') {
+ pathEnd++;
+ }
+
+ queryStart = queryEnd = pathEnd;
+
+ if (url[queryStart] == '?') {
+ while (url[queryEnd] != '\0' && url[queryEnd] != '#') {
+ queryEnd++;
+ }
+ }
+
+ fragmentStart = fragmentEnd = queryEnd;
+
+ if (url[fragmentStart] == '#') {
+ fragmentStart++;
+ // FIXME: don't use strlen, counting up should be faster
+ fragmentEnd = fragmentStart + strlen(url + fragmentStart);
+ }
+ }
+
+ // assemble it all, remembering the real ranges
+
+ urlString = QString(url, schemeEnd + 1);
+ schemeEndPos = schemeEnd;
+
+ QString authority;
+ if (userEnd != userStart) {
+ authority += QString(url + userStart, userEnd - userStart);
+ }
+
+ userEndPos = authority.length();
+
+ if (passwordEnd != passwordStart) {
+ // start ahead one to include the colon
+ authority += QString(url + passwordStart - 1, passwordEnd - passwordStart + 1);
+ }
+
+ passwordEndPos = authority.length();
+
+ if (!authority.isEmpty()) {
+ authority += "@";
+ }
+
+ if (hostEnd != hostStart) {
+ authority += QString(url + hostStart, hostEnd - hostStart);
+ }
+
+ hostEndPos = authority.length();
+
+ if (portEnd != portStart) {
+ // start ahead one to include the colon
+ authority += QString(url + portStart -1, portEnd - portStart + 1);
+ }
+
+ portEndPos = authority.length();
+
+ if (!authority.isEmpty() && authority != "localhost") {
+ userStartPos = urlString.length() + 2;
+ userEndPos += userStartPos;
+ passwordEndPos += userStartPos;
+ hostEndPos += userStartPos;
+ portEndPos += userStartPos;
+
+ urlString += "//" + authority;
+ } else {
+ userStartPos = userEndPos = urlString.length();
+ passwordEndPos = userStartPos;
+ hostEndPos = userStartPos;
+ portEndPos = userStartPos;
+ }
+
+ if (pathEnd != pathStart) {
+ QString path(url + pathStart, pathEnd - pathStart);
+ urlString += escapeBadChars(path);
+ }
+ pathEndPos = urlString.length();
+
+ if (queryEnd != queryStart) {
+ urlString += escapeBadChars(QString(url + queryStart, queryEnd - queryStart));
+ }
+ queryEndPos = urlString.length();
+
+ if (fragmentEnd != fragmentStart) {
+ urlString += "#" + escapeBadChars(QString(url + fragmentStart, fragmentEnd - fragmentStart));
}
+ fragmentEndPos = urlString.length();
}
NSURL *KURL::getNSURL() const
{
- parse();
- return [[(NSURL *)d->urlRef retain] autorelease];
+ return [NSURL URLWithString:urlString.getNSString()];
}
QString KURL::encodedHtmlRef() const
diff --git a/WebCore/kwq/kdecore/kurl.h b/WebCore/kwq/kdecore/kurl.h
index 8b2cdfc..2523ee7 100644
--- a/WebCore/kwq/kdecore/kurl.h
+++ b/WebCore/kwq/kdecore/kurl.h
@@ -43,17 +43,12 @@ public:
KURL(const KURL &, const QString &);
KURL(const QString &, int encoding_hint=0);
- KURL(const KURL &);
-
- ~KURL();
- KURL &operator=(const KURL &);
-
- bool isEmpty() const;
- bool isMalformed() const;
- bool isValid() const { return !isMalformed(); }
+ inline bool isEmpty() const { return urlString.isEmpty(); }
+ inline bool isMalformed() const { return !m_isValid; }
+ inline bool isValid() const { return m_isValid; }
bool hasPath() const;
- QString url() const;
+ inline QString url() const { return urlString; }
QString protocol() const;
QString host() const;
unsigned short int port() const;
@@ -77,22 +72,23 @@ public:
NSURL *getNSURL() const;
static QString decode_string(const QString &urlString);
- static void clearCaches();
friend bool operator==(const KURL &, const KURL &);
private:
- void swap(KURL &other);
- void copyOnWrite();
- void parse() const;
- void assemble();
- QString normalizeURLString(const QString &s);
- QString normalizeRelativeURLString(const KURL &base, const QString &relative);
-
- class KWQKURLPrivate;
+ void parse(const char *url);
- mutable KWQRefPtr<KWQKURLPrivate> d;
QString urlString;
+ bool m_isValid;
+ int schemeEndPos;
+ int userStartPos;
+ int userEndPos;
+ int passwordEndPos;
+ int hostEndPos;
+ int portEndPos;
+ int pathEndPos;
+ int queryEndPos;
+ int fragmentEndPos;
};
#endif
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list