1878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org/*
2878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org **********************************************************************
3878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org *   Copyright (C) 2005-2006, International Business Machines
4878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org *   Corporation and others.  All Rights Reserved.
5878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org **********************************************************************
6878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org */
7878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
8878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org#include "unicode/utypes.h"
9878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
10878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org#if !UCONFIG_NO_CONVERSION
11878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
12878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org#include "csrucode.h"
13878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
14878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgU_NAMESPACE_BEGIN
15878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
16878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgCharsetRecog_Unicode::~CharsetRecog_Unicode()
17878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
18878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    // nothing to do
19878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
20878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
21878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgCharsetRecog_UTF_16_BE::~CharsetRecog_UTF_16_BE()
22878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
23878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    // nothing to do
24878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
25878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
26878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgconst char *CharsetRecog_UTF_16_BE::getName() const
27878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
28878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    return "UTF-16BE";
29878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
30878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
31878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgint32_t CharsetRecog_UTF_16_BE::match(InputText* textIn)
32878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
33878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    const uint8_t *input = textIn->fRawInput;
346c837760feb38bc3d489542d1d430feec960cf6cjshin@chromium.org    int32_t length = textIn->fRawLength;
35878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
366c837760feb38bc3d489542d1d430feec960cf6cjshin@chromium.org    if (length >=2 && input[0] == 0xFE && input[1] == 0xFF) {
37878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        return 100;
38878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    }
39878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
40878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    // TODO: Do some statastics to check for unsigned UTF-16BE
41878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    return 0;
42878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
43878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
44878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgCharsetRecog_UTF_16_LE::~CharsetRecog_UTF_16_LE()
45878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
46878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    // nothing to do
47878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
48878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
49878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgconst char *CharsetRecog_UTF_16_LE::getName() const
50878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
51878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    return "UTF-16LE";
52878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
53878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
54878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgint32_t CharsetRecog_UTF_16_LE::match(InputText* textIn)
55878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
56878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    const uint8_t *input = textIn->fRawInput;
576c837760feb38bc3d489542d1d430feec960cf6cjshin@chromium.org    int32_t length = textIn->fRawLength;
58878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
596c837760feb38bc3d489542d1d430feec960cf6cjshin@chromium.org    if (length >= 4 && input[0] == 0xFF && input[1] == 0xFE && (input[2] != 0x00 || input[3] != 0x00)) {
60878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        return 100;
61878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    }
62878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
63878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    // TODO: Do some statastics to check for unsigned UTF-16LE
64878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    return 0;
65878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
66878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
67878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgCharsetRecog_UTF_32::~CharsetRecog_UTF_32()
68878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
69878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    // nothing to do
70878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
71878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
72878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgint32_t CharsetRecog_UTF_32::match(InputText* textIn)
73878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
74878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    const uint8_t *input = textIn->fRawInput;
75878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    int32_t limit = (textIn->fRawLength / 4) * 4;
76878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    int32_t numValid = 0;
77878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    int32_t numInvalid = 0;
78878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    bool hasBOM = FALSE;
79878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    int32_t confidence = 0;
80878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
816c837760feb38bc3d489542d1d430feec960cf6cjshin@chromium.org    if (limit > 0 && getChar(input, 0) == 0x0000FEFFUL) {
82878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        hasBOM = TRUE;
83878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    }
84878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
85878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    for(int32_t i = 0; i < limit; i += 4) {
86878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        int32_t ch = getChar(input, i);
87878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
88878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        if (ch < 0 || ch >= 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF)) {
89878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org            numInvalid += 1;
90878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        } else {
91878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org            numValid += 1;
92878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        }
93878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    }
94878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
95878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
96878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    // Cook up some sort of confidence score, based on presense of a BOM
97878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    //    and the existence of valid and/or invalid multi-byte sequences.
98878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    if (hasBOM && numInvalid==0) {
99878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        confidence = 100;
100878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    } else if (hasBOM && numValid > numInvalid*10) {
101878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        confidence = 80;
102878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    } else if (numValid > 3 && numInvalid == 0) {
103878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        confidence = 100;
104878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    } else if (numValid > 0 && numInvalid == 0) {
105878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        confidence = 80;
106878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    } else if (numValid > numInvalid*10) {
107878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        // Probably corruput UTF-32BE data.  Valid sequences aren't likely by chance.
108878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org        confidence = 25;
109878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    }
110878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
111878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    return confidence;
112878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
113878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
114878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgCharsetRecog_UTF_32_BE::~CharsetRecog_UTF_32_BE()
115878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
116878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    // nothing to do
117878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
118878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
119878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgconst char *CharsetRecog_UTF_32_BE::getName() const
120878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
121878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    return "UTF-32BE";
122878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
123878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
124878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgint32_t CharsetRecog_UTF_32_BE::getChar(const uint8_t *input, int32_t index) const
125878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
126878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    return input[index + 0] << 24 | input[index + 1] << 16 |
127878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org           input[index + 2] <<  8 | input[index + 3];
128878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
129878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
130878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgCharsetRecog_UTF_32_LE::~CharsetRecog_UTF_32_LE()
131878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
132878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    // nothing to do
133878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
134878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
135878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgconst char *CharsetRecog_UTF_32_LE::getName() const
136878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
137878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    return "UTF-32LE";
138878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
139878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
140878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgint32_t CharsetRecog_UTF_32_LE::getChar(const uint8_t *input, int32_t index) const
141878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org{
142878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org    return input[index + 3] << 24 | input[index + 2] << 16 |
143878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org           input[index + 1] <<  8 | input[index + 0];
144878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org}
145878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
146878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.orgU_NAMESPACE_END
147878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org#endif
148878ab27c8e23bae140344313af953fe99cf89b3jshin@chromium.org
149