зеркало из https://github.com/mozilla/pjs.git
Bug 254252 nsCRT::BufferHashCode has two variants, and only one user, HashCodeAsUTF8 has no users
patch by mikael@parknert.se r=darin sr=bz
This commit is contained in:
Родитель
d08ce10f76
Коммит
7380c4ec49
|
@ -1,380 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef nsHTMLValue_h___
|
||||
#define nsHTMLValue_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsColor.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIAtom.h"
|
||||
|
||||
class nsIDocument;
|
||||
class nsICSSStyleRule;
|
||||
|
||||
class nsCheapStringBufferUtils {
|
||||
public:
|
||||
/**
|
||||
* Get the string pointer
|
||||
* @param aBuf the buffer
|
||||
* @return a pointer to the string
|
||||
*/
|
||||
static const PRUnichar* StrPtr(const PRUnichar* aBuf) {
|
||||
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
||||
return (const PRUnichar*)( ((const char*)aBuf) + sizeof(PRUint32) );
|
||||
}
|
||||
static PRUnichar* StrPtr(PRUnichar* aBuf) {
|
||||
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
||||
return (PRUnichar*)( ((char*)aBuf) + sizeof(PRUint32) );
|
||||
}
|
||||
/**
|
||||
* Get the string length
|
||||
* @param aBuf the buffer
|
||||
* @return the string length
|
||||
*/
|
||||
static PRUint32 Length(const PRUnichar* aBuf) {
|
||||
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
||||
return *((PRUint32*)aBuf);
|
||||
}
|
||||
/**
|
||||
* Get a DependentString from a buffer
|
||||
*
|
||||
* @param aBuf the buffer to get string from
|
||||
* @return a DependentString representing this string
|
||||
*/
|
||||
static nsDependentSubstring GetDependentString(const PRUnichar* aBuf) {
|
||||
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
||||
const PRUnichar* buf = StrPtr(aBuf);
|
||||
return Substring(buf, buf + Length(aBuf));
|
||||
}
|
||||
/**
|
||||
* Construct from an AString
|
||||
* @param aBuf the buffer to copy to
|
||||
* @param aStr the string to construct from
|
||||
*/
|
||||
static void CopyToBuffer(PRUnichar*& aBuf, const nsAString& aStr) {
|
||||
PRUint32 len = aStr.Length();
|
||||
aBuf = (PRUnichar*)nsMemory::Alloc(sizeof(PRUint32) +
|
||||
len * sizeof(PRUnichar));
|
||||
*((PRUint32*)aBuf) = len;
|
||||
CopyUnicodeTo(aStr, 0, StrPtr(aBuf), len);
|
||||
}
|
||||
/**
|
||||
* Construct from an AString
|
||||
* @param aBuf the buffer to copy to
|
||||
* @param aStr the string to construct from
|
||||
*/
|
||||
static void CopyToExistingBuffer(PRUnichar*& aBuf, PRUnichar* aOldBuf,
|
||||
const nsAString& aStr) {
|
||||
NS_ASSERTION(aOldBuf, "Cannot work on null buffer!");
|
||||
PRUint32 len = aStr.Length();
|
||||
aBuf = NS_STATIC_CAST(PRUnichar*,
|
||||
nsMemory::Realloc(aOldBuf, sizeof(PRUint32) +
|
||||
len * sizeof(PRUnichar)));
|
||||
*(NS_REINTERPRET_CAST(PRUint32*, aBuf)) = len;
|
||||
CopyUnicodeTo(aStr, 0, StrPtr(aBuf), len);
|
||||
}
|
||||
/**
|
||||
* Construct from another nsCheapStringBuffer
|
||||
* @param aBuf the buffer to put into
|
||||
* @param aSrc the buffer to construct from
|
||||
*/
|
||||
static void Clone(PRUnichar*& aBuf, const PRUnichar* aSrc) {
|
||||
NS_ASSERTION(aSrc, "Cannot work on null buffer!");
|
||||
aBuf = (PRUnichar*)nsMemory::Clone(aSrc, sizeof(PRUint32) +
|
||||
Length(aSrc) * sizeof(PRUnichar));
|
||||
}
|
||||
/**
|
||||
* Free the memory for the buf
|
||||
* @param aBuf the buffer to free
|
||||
*/
|
||||
static void Free(PRUnichar* aBuf) {
|
||||
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
||||
nsMemory::Free(aBuf);
|
||||
}
|
||||
/**
|
||||
* Get a hashcode for the buffer
|
||||
* @param aBuf the buffer
|
||||
* @return the hashcode
|
||||
*/
|
||||
static PRUint32 HashCode(const PRUnichar* aBuf) {
|
||||
NS_ASSERTION(aBuf, "Cannot work on null buffer!");
|
||||
return nsCRT::BufferHashCode((char*)StrPtr(aBuf),
|
||||
Length(aBuf)*sizeof(PRUnichar));
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// nsHTMLUnit is two bytes: the class of type, and a specifier to distinguish
|
||||
// between different things stored as the same type. Doing
|
||||
// mUnit & HTMLUNIT_CLASS_MASK should give you the class of type.
|
||||
//
|
||||
#define HTMLUNIT_STRING 0x0100
|
||||
#define HTMLUNIT_INTEGER 0x0200
|
||||
#define HTMLUNIT_COLOR 0x0800
|
||||
#define HTMLUNIT_CSSSTYLERULE 0x1000
|
||||
#define HTMLUNIT_PERCENT 0x2000
|
||||
#define HTMLUNIT_ATOMARRAY 0x4000
|
||||
#define HTMLUNIT_CLASS_MASK 0xff00
|
||||
|
||||
enum nsHTMLUnit {
|
||||
// a string value
|
||||
eHTMLUnit_String = HTMLUNIT_STRING,
|
||||
|
||||
// a simple int value
|
||||
eHTMLUnit_Integer = HTMLUNIT_INTEGER,
|
||||
// value has enumerated meaning
|
||||
eHTMLUnit_Enumerated = HTMLUNIT_INTEGER | 1,
|
||||
// value is a relative proportion of some whole
|
||||
eHTMLUnit_Proportional = HTMLUNIT_INTEGER | 2,
|
||||
|
||||
// an RGBA value
|
||||
eHTMLUnit_Color = HTMLUNIT_COLOR,
|
||||
|
||||
// a nsICSSStyleRule
|
||||
eHTMLUnit_CSSStyleRule = HTMLUNIT_CSSSTYLERULE,
|
||||
|
||||
// (1.0 == 100%) value is percentage of something
|
||||
eHTMLUnit_Percent = HTMLUNIT_PERCENT,
|
||||
|
||||
// an array of atoms
|
||||
eHTMLUnit_AtomArray = HTMLUNIT_ATOMARRAY
|
||||
};
|
||||
|
||||
/**
|
||||
* Class which is used to represent the value of an attribute of an
|
||||
* HTML element. The value has a unit which is an nsHTMLUnit;
|
||||
* checking the unit is a must before asking for the value in any
|
||||
* particular form.
|
||||
*/
|
||||
class nsHTMLValue {
|
||||
public:
|
||||
nsHTMLValue();
|
||||
nsHTMLValue(PRInt32 aValue, nsHTMLUnit aUnit);
|
||||
~nsHTMLValue(void);
|
||||
|
||||
|
||||
/**
|
||||
* Get the unit of this HTMLValue
|
||||
* @return the unit of this HTMLValue
|
||||
*/
|
||||
nsHTMLUnit GetUnit(void) const { return (nsHTMLUnit)mUnit; }
|
||||
|
||||
PRInt32 GetIntValue(void) const;
|
||||
float GetPercentValue(void) const;
|
||||
nsAString& GetStringValue(nsAString& aBuffer) const;
|
||||
PRBool GetColorValue(nscolor& aColor) const;
|
||||
|
||||
PRBool IsEmptyString() const;
|
||||
|
||||
/**
|
||||
* Reset the string to null type, freeing things in the process if necessary.
|
||||
*/
|
||||
void Reset(void);
|
||||
void SetIntValue(PRInt32 aValue, nsHTMLUnit aUnit);
|
||||
void SetPercentValue(float aValue);
|
||||
void SetStringValue(const nsAString& aValue, nsHTMLUnit aUnit = eHTMLUnit_String);
|
||||
void SetCSSStyleRuleValue(nsICSSStyleRule* aValue);
|
||||
void SetAtomArrayValue(nsCOMArray<nsIAtom>* aValue);
|
||||
void SetColorValue(nscolor aValue);
|
||||
|
||||
/**
|
||||
* Structure for a mapping from int (enum) values to strings. When you use
|
||||
* it you generally create an array of them.
|
||||
* Instantiate like this:
|
||||
* EnumTable myTable[] = {
|
||||
* { "string1", 1 },
|
||||
* { "string2", 2 },
|
||||
* { 0 }
|
||||
* }
|
||||
*/
|
||||
struct EnumTable {
|
||||
/** The string the value maps to */
|
||||
const char* tag;
|
||||
/** The enum value that maps to this string */
|
||||
PRInt16 value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse and output this HTMLValue in a variety of ways
|
||||
*/
|
||||
// Attribute parsing utilities
|
||||
|
||||
/**
|
||||
* Map an enum HTMLValue to its string
|
||||
*
|
||||
* @param aValue the HTMLValue with the int in it
|
||||
* @param aTable the enumeration to map with
|
||||
* @param aResult the string the value maps to [OUT]
|
||||
* @return whether the enum value was found or not
|
||||
*/
|
||||
PRBool EnumValueToString(const EnumTable* aTable,
|
||||
nsAString& aResult) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The unit of the value
|
||||
* @see nsHTMLUnit
|
||||
*/
|
||||
PRUint32 mUnit;
|
||||
|
||||
/**
|
||||
* The actual value. Please to not be adding more-than-4-byte things to this
|
||||
* union.
|
||||
*/
|
||||
union {
|
||||
/** Int. */
|
||||
PRInt32 mInt;
|
||||
/** Float. */
|
||||
float mFloat;
|
||||
/** String. First 4 bytes are the length, non-null-terminated. */
|
||||
PRUnichar* mString;
|
||||
/** nsICSSStyleRule. Strong reference. */
|
||||
nsICSSStyleRule* mCSSStyleRule;
|
||||
/** Color. */
|
||||
nscolor mColor;
|
||||
/** Array if atoms */
|
||||
nsCOMArray<nsIAtom>* mAtomArray;
|
||||
} mValue;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Helper to set string value (checks for embedded nulls or length); verifies
|
||||
* that aUnit is a string type as well.
|
||||
* @param aValue the value to set
|
||||
* @param aUnit the unit to set
|
||||
*/
|
||||
void SetStringValueInternal(const nsAString& aValue, nsHTMLUnit aUnit);
|
||||
/**
|
||||
* Get a DependentString from mValue.mString (if the string is stored with
|
||||
* length, passes that information to the DependentString). Do not call this
|
||||
* if mValue.mString is null.
|
||||
*
|
||||
* @return a DependentString representing this string
|
||||
*/
|
||||
nsDependentSubstring GetDependentString() const;
|
||||
/**
|
||||
* Get the unit class (HTMLUNIT_*)
|
||||
* @return the unit class
|
||||
*/
|
||||
PRUint32 GetUnitClass() const { return mUnit & HTMLUNIT_CLASS_MASK; }
|
||||
|
||||
nsHTMLValue(const nsHTMLValue& aCopy); // NOT TO BE IMPLEMENTED
|
||||
PRBool operator==(const nsHTMLValue& aOther) const; // NOT TO BE IMPLEMENTED
|
||||
nsHTMLValue& operator=(const nsHTMLValue& aCopy); // NOT TO BE IMPLEMENTED
|
||||
PRBool operator!=(const nsHTMLValue& aOther) const; // NOT TO BE IMPLEMENTED
|
||||
};
|
||||
|
||||
inline nsDependentSubstring nsHTMLValue::GetDependentString() const
|
||||
{
|
||||
NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING,
|
||||
"Some dork called GetDependentString() on a non-string!");
|
||||
static const PRUnichar blankStr[] = { '\0' };
|
||||
return mValue.mString
|
||||
? nsCheapStringBufferUtils::GetDependentString(mValue.mString)
|
||||
: Substring(blankStr, blankStr);
|
||||
}
|
||||
|
||||
inline PRInt32 nsHTMLValue::GetIntValue(void) const
|
||||
{
|
||||
NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING ||
|
||||
GetUnitClass() == HTMLUNIT_INTEGER,
|
||||
"not an int value");
|
||||
PRUint32 unitClass = GetUnitClass();
|
||||
if (unitClass == HTMLUNIT_INTEGER) {
|
||||
return mValue.mInt;
|
||||
}
|
||||
|
||||
if (unitClass == HTMLUNIT_STRING) {
|
||||
if (mValue.mString) {
|
||||
PRInt32 err=0;
|
||||
// XXX this copies. new string APIs will make this better, right?
|
||||
nsAutoString str(GetDependentString());
|
||||
return str.ToInteger(&err);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline float nsHTMLValue::GetPercentValue(void) const
|
||||
{
|
||||
NS_ASSERTION(mUnit == eHTMLUnit_Percent, "not a percent value");
|
||||
if (mUnit == eHTMLUnit_Percent) {
|
||||
return mValue.mFloat;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
inline nsAString& nsHTMLValue::GetStringValue(nsAString& aBuffer) const
|
||||
{
|
||||
NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING,
|
||||
"not a string value");
|
||||
if (GetUnitClass() == HTMLUNIT_STRING && mValue.mString) {
|
||||
aBuffer = GetDependentString();
|
||||
} else {
|
||||
aBuffer.Truncate();
|
||||
}
|
||||
return aBuffer;
|
||||
}
|
||||
|
||||
inline PRBool nsHTMLValue::GetColorValue(nscolor& aColor) const
|
||||
{
|
||||
NS_ASSERTION((mUnit == eHTMLUnit_Color) || (mUnit == eHTMLUnit_String),
|
||||
"not a color value");
|
||||
if (mUnit == eHTMLUnit_Color) {
|
||||
aColor = mValue.mColor;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (mUnit == eHTMLUnit_String && mValue.mString) {
|
||||
return NS_ColorNameToRGB(GetDependentString(), &aColor);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
inline PRBool nsHTMLValue::IsEmptyString() const
|
||||
{
|
||||
return mUnit == eHTMLUnit_String && !mValue.mString;
|
||||
}
|
||||
|
||||
#endif /* nsHTMLValue_h___ */
|
||||
|
|
@ -300,105 +300,6 @@ PRUint32 nsCRT::HashCode(const PRUnichar* str, PRUint32* resultingStrLen)
|
|||
return h;
|
||||
}
|
||||
|
||||
PRUint32 nsCRT::HashCodeAsUTF8(const PRUnichar* str, PRUint32* resultingStrLen)
|
||||
{
|
||||
PRUint32 h = 0;
|
||||
const PRUnichar* s = str;
|
||||
|
||||
{
|
||||
PRUint16 W1 = 0; // the first UTF-16 word in a two word tuple
|
||||
PRUint32 U = 0; // the current char as UCS-4
|
||||
int code_length = 0; // the number of bytes in the UTF-8 sequence for the current char
|
||||
|
||||
PRUint16 W;
|
||||
while ( (W = *s++) )
|
||||
{
|
||||
/*
|
||||
* On the fly, decoding from UTF-16 (and/or UCS-2) into UTF-8 as per
|
||||
* http://www.ietf.org/rfc/rfc2781.txt
|
||||
* http://www.ietf.org/rfc/rfc2279.txt
|
||||
*/
|
||||
|
||||
if ( !W1 )
|
||||
{
|
||||
if ( W < 0xD800 || 0xDFFF < W )
|
||||
{
|
||||
U = W;
|
||||
if ( W <= 0x007F )
|
||||
code_length = 1;
|
||||
else if ( W <= 0x07FF )
|
||||
code_length = 2;
|
||||
else
|
||||
code_length = 3;
|
||||
}
|
||||
else if ( /* 0xD800 <= W1 && */ W <= 0xDBFF )
|
||||
W1 = W;
|
||||
}
|
||||
else
|
||||
{
|
||||
// as required by the standard, this code is careful to
|
||||
// throw out illegal sequences
|
||||
|
||||
if ( 0xDC00 <= W && W <= 0xDFFF )
|
||||
{
|
||||
U = PRUint32( (W1&0x03FF)<<10 | (W&0x3FFF) );
|
||||
if ( U <= 0x001FFFFF )
|
||||
code_length = 4;
|
||||
else if ( U <= 0x3FFFFFF )
|
||||
code_length = 5;
|
||||
else
|
||||
code_length = 6;
|
||||
}
|
||||
W1 = 0;
|
||||
}
|
||||
|
||||
|
||||
if ( code_length > 0 )
|
||||
{
|
||||
static const PRUint16 sBytePrefix[7] = { 0x0000, 0x0000, 0x00C0, 0x00E0, 0x00F0, 0x00F8, 0x00FC };
|
||||
static const PRUint16 sShift[7] = { 0, 0, 6, 12, 18, 24, 30 };
|
||||
|
||||
/*
|
||||
* Unlike the algorithm in http://www.ietf.org/rfc/rfc2279.txt
|
||||
* we must calculate the bytes in left to right order so that
|
||||
* our hash result matches what the narrow version would calculate
|
||||
* on an already UTF-8 string.
|
||||
*/
|
||||
|
||||
// hash the first (and often, only, byte)
|
||||
h = (h>>28) ^ (h<<4) ^ (sBytePrefix[code_length] | (U>>sShift[code_length]));
|
||||
|
||||
// an unrolled loop for hashing any remaining bytes in this sequence
|
||||
switch ( code_length )
|
||||
{ // falling through in each case
|
||||
case 6: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>24) & 0x003F));
|
||||
case 5: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>18) & 0x003F));
|
||||
case 4: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>12) & 0x003F));
|
||||
case 3: h = (h>>28) ^ (h<<4) ^ (0x80 | ((U>>6 ) & 0x003F));
|
||||
case 2: h = (h>>28) ^ (h<<4) ^ (0x80 | ( U & 0x003F));
|
||||
default: code_length = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( resultingStrLen )
|
||||
*resultingStrLen = (s-str)-1;
|
||||
return h;
|
||||
}
|
||||
|
||||
PRUint32 nsCRT::BufferHashCode(const char* s, PRUint32 len)
|
||||
{
|
||||
PRUint32 h = 0;
|
||||
const char* done = s + len;
|
||||
|
||||
while ( s < done )
|
||||
h = (h>>28) ^ (h<<4) ^ PRUint8(*s++); // cast to unsigned to prevent possible sign extension
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
PRUint32 nsCRT::BufferHashCode(const PRUnichar* s, PRUint32 len)
|
||||
{
|
||||
PRUint32 h = 0;
|
||||
|
|
|
@ -233,15 +233,6 @@ public:
|
|||
static PRUint32 HashCode(const PRUnichar* str,
|
||||
PRUint32* resultingStrLen = nsnull);
|
||||
|
||||
// Computes a hashcode for a ucs2 string that returns the same thing
|
||||
// as the HashCode method taking a |char*| would if the string were
|
||||
// converted to UTF8. Returns the string length as an added bonus.
|
||||
static PRUint32 HashCodeAsUTF8(const PRUnichar* str,
|
||||
PRUint32* resultingStrLen = nsnull);
|
||||
|
||||
// Computes the hashcode for a buffer with a specified length.
|
||||
static PRUint32 BufferHashCode(const char* str, PRUint32 strLen);
|
||||
|
||||
// Computes the hashcode for a buffer with a specified length.
|
||||
static PRUint32 BufferHashCode(const PRUnichar* str, PRUint32 strLen);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче