#include "config.h"
#include "CharsetNames.h"
#include "CharsetData.h"
#include <wtf/Assertions.h>
#include <wtf/HashMap.h>
#include <unicode/ucnv.h>
using namespace WTF;
namespace WebCore {
struct TextEncodingIDHashTraits : GenericHashTraits<TextEncodingID> {
static const bool emptyValueIsZero = false;
static TraitType emptyValue() { return InvalidEncoding; }
static TraitType deletedValue() { return InvalidEncoding2; }
};
const unsigned PHI = 0x9e3779b9U;
struct EncodingNameHash {
static bool equal(const char* s1, const char* s2)
{
char c1;
char c2;
do {
do
c1 = *s1++;
while (c1 && !isalnum(c1));
do
c2 = *s2++;
while (c2 && !isalnum(c2));
if (tolower(c1) != tolower(c2))
return false;
} while (c1 && c2);
return !c1 && !c2;
}
static unsigned hash(const char* s)
{
unsigned h = PHI;
for (int i = 0; i != 16; ++i) {
char c;
do
c = *s++;
while (c && !isalnum(c));
if (!c)
break;
h += tolower(c);
h += (h << 10);
h ^= (h >> 6);
}
h += (h << 3);
h ^= (h >> 11);
h += (h << 15);
return h;
}
};
typedef HashMap<const char*, const CharsetEntry*, EncodingNameHash> NameMap;
typedef HashMap<TextEncodingID, const CharsetEntry*, IntHash<TextEncodingID>, TextEncodingIDHashTraits> EncodingMap;
static NameMap* nameMap;
static EncodingMap* encodingMap;
static void buildCharsetMaps()
{
ASSERT(!nameMap);
ASSERT(!encodingMap);
nameMap = new NameMap;
encodingMap = new EncodingMap;
for (int i = 0; CharsetTable[i].name; ++i) {
ASSERT(CharsetTable[i].encoding != TextEncodingIDHashTraits::emptyValue());
ASSERT(CharsetTable[i].encoding != TextEncodingIDHashTraits::deletedValue());
nameMap->add(CharsetTable[i].name, &CharsetTable[i]);
encodingMap->add(CharsetTable[i].encoding, &CharsetTable[i]);
}
}
TextEncodingID textEncodingIDFromCharsetName(const char* name, TextEncodingFlags* flags)
{
if (!nameMap)
buildCharsetMaps();
const CharsetEntry* entry = nameMap->get(name);
if (!entry) {
UErrorCode err = U_ZERO_ERROR;
const char* standardName = ucnv_getStandardName(name, "IANA", &err);
if (!standardName || !(entry = nameMap->get(standardName))) {
if (flags)
*flags = NoEncodingFlags;
return InvalidEncoding;
}
}
if (flags)
*flags = static_cast<TextEncodingFlags>(entry->flags);
return entry->encoding;
}
const char* charsetNameFromTextEncodingID(TextEncodingID encoding)
{
if (!encodingMap)
buildCharsetMaps();
const CharsetEntry* entry = encodingMap->get(encoding);
if (!entry)
return 0;
return entry->name;
}
}