[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