Bug 125608: Reduce size of nsStandardURLs by average of 27+ bytes. r=bz

This commit is contained in:
Randell Jesup 2011-06-07 12:17:40 -04:00
parent 08886a8947
commit bea04639ac
2 changed files with 52 additions and 15 deletions

View File

@ -177,8 +177,12 @@ nsSegmentEncoder::EncodeSegmentCount(const char *str,
const URLSegment &seg,
PRInt16 mask,
nsAFlatCString &result,
PRBool &appended)
PRBool &appended,
PRUint32 extraLen)
{
// extraLen is characters outside the segment that will be
// added when the segment is not empty (like the @ following
// a username).
appended = PR_FALSE;
if (!str)
return 0;
@ -220,6 +224,7 @@ nsSegmentEncoder::EncodeSegmentCount(const char *str,
len = encBuf.Length();
appended = PR_TRUE;
}
len += extraLen;
}
return len;
}
@ -498,16 +503,19 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
encBasename, encExtension, encParam, encQuery, encRef;
PRBool useEncUsername, useEncPassword, useEncHost, useEncDirectory,
useEncBasename, useEncExtension, useEncParam, useEncQuery, useEncRef;
nsCAutoString portbuf;
//
// escape each URL segment, if necessary, and calculate approximate normalized
// spec length.
//
PRUint32 approxLen = 3; // includes room for "://"
// [scheme://][username[:password]@]host[:port]/path[;param][?query_string][#ref]
PRUint32 approxLen = 0;
// the scheme is already ASCII
if (mScheme.mLen > 0)
approxLen += mScheme.mLen;
approxLen += mScheme.mLen + 3; // includes room for "://";
// encode URL segments; convert UTF-8 to origin charset and possibly escape.
// results written to encXXX variables only if |spec| is not already in the
@ -515,14 +523,37 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
{
GET_SEGMENT_ENCODER(encoder);
GET_QUERY_ENCODER(queryEncoder);
approxLen += encoder.EncodeSegmentCount(spec, mUsername, esc_Username, encUsername, useEncUsername);
approxLen += encoder.EncodeSegmentCount(spec, mPassword, esc_Password, encPassword, useEncPassword);
approxLen += encoder.EncodeSegmentCount(spec, mDirectory, esc_Directory, encDirectory, useEncDirectory);
// Items using an extraLen of 1 don't add anything unless mLen > 0
// Username@
approxLen += encoder.EncodeSegmentCount(spec, mUsername, esc_Username, encUsername, useEncUsername, 1);
// :Password
approxLen += encoder.EncodeSegmentCount(spec, mPassword, esc_Password, encPassword, useEncPassword, 1);
// mHost is handled differently below due to encoding differences
NS_ABORT_IF_FALSE(mPort > 0 || mPort == -1, "Invalid negative mPort");
if (mPort != -1 && mPort != mDefaultPort)
{
// :port
portbuf.AppendInt(mPort);
approxLen += portbuf.Length() + 1;
}
approxLen += 1; // reserve space for possible leading '/' - may not be needed
// Should just use mPath? These are pessimistic, and thus waste space
approxLen += encoder.EncodeSegmentCount(spec, mDirectory, esc_Directory, encDirectory, useEncDirectory, 1);
approxLen += encoder.EncodeSegmentCount(spec, mBasename, esc_FileBaseName, encBasename, useEncBasename);
approxLen += encoder.EncodeSegmentCount(spec, mExtension, esc_FileExtension, encExtension, useEncExtension);
approxLen += encoder.EncodeSegmentCount(spec, mParam, esc_Param, encParam, useEncParam);
approxLen += queryEncoder.EncodeSegmentCount(spec, mQuery, esc_Query, encQuery, useEncQuery);
approxLen += encoder.EncodeSegmentCount(spec, mRef, esc_Ref, encRef, useEncRef);
approxLen += encoder.EncodeSegmentCount(spec, mExtension, esc_FileExtension, encExtension, useEncExtension, 1);
// These next ones *always* add their leading character even if length is 0
// Handles items like "http://#"
// ;param
if (mParam.mLen >= 0)
approxLen += 1 + encoder.EncodeSegmentCount(spec, mParam, esc_Param, encParam, useEncParam);
// ?query
if (mQuery.mLen >= 0)
approxLen += 1 + queryEncoder.EncodeSegmentCount(spec, mQuery, esc_Query, encQuery, useEncQuery);
// #ref
if (mRef.mLen >= 0)
approxLen += 1 + encoder.EncodeSegmentCount(spec, mRef, esc_Ref, encRef, useEncRef);
}
// do not escape the hostname, if IPv6 address literal, mHost will
@ -545,7 +576,8 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
//
// generate the normalized URL string
//
if (!EnsureStringLength(mSpec, approxLen + 32))
// approxLen should be correct or 1 high
if (!EnsureStringLength(mSpec, approxLen+1)) // buf needs a trailing '\0' below
return NS_ERROR_OUT_OF_MEMORY;
char *buf;
mSpec.BeginWriting(buf);
@ -572,10 +604,10 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
if (mHost.mLen > 0) {
i = AppendSegmentToBuf(buf, i, spec, mHost, &encHost, useEncHost);
net_ToLowerCase(buf + mHost.mPos, mHost.mLen);
NS_ABORT_IF_FALSE(mPort > 0 || mPort == -1, "Invalid negative mPort");
if (mPort != -1 && mPort != mDefaultPort) {
nsCAutoString portbuf;
portbuf.AppendInt(mPort);
buf[i++] = ':';
// Already formatted while building approxLen
i = AppendToBuf(buf, i, portbuf.get(), portbuf.Length());
}
}
@ -663,7 +695,7 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
CoalescePath(coalesceFlag, buf + mDirectory.mPos);
}
mSpec.SetLength(strlen(buf));
NS_ASSERTION(mSpec.Length() <= approxLen+32, "We've overflowed the mSpec buffer!");
NS_ASSERTION(mSpec.Length() <= approxLen, "We've overflowed the mSpec buffer!");
return NS_OK;
}
@ -1495,6 +1527,10 @@ nsStandardURL::SetPort(PRInt32 port)
if ((port == mPort) || (mPort == -1 && port == mDefaultPort))
return NS_OK;
// ports must be >= 0 (and 0 is pretty much garbage too, though legal per RFC)
if (port <= 0 && port != -1) // -1 == use default
return NS_ERROR_MALFORMED_URI;
if (mURLType == URLTYPE_NO_AUTHORITY) {
NS_WARNING("cannot set port on no-auth url");
return NS_ERROR_UNEXPECTED;

View File

@ -135,7 +135,8 @@ public: /* internal -- HPUX compiler can't handle this being private */
const URLSegment &segment,
PRInt16 mask,
nsAFlatCString &buf,
PRBool& appended);
PRBool& appended,
PRUint32 extraLen = 0);
// Encode the given string if necessary, and return a reference to
// the encoded string. Returns a reference to |buf| if encoding