Coverage Report

Created: 2026-10-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/kcodecs/src/probers/CharDistribution.h
Line
Count
Source
1
/*  -*- C++ -*-
2
    SPDX-FileCopyrightText: 1998 Netscape Communications Corporation <developer@mozilla.org>
3
4
    SPDX-License-Identifier: MIT
5
*/
6
7
#ifndef CharDistribution_h__
8
#define CharDistribution_h__
9
10
#include "kcodecs_export.h"
11
12
#include <cstdint>
13
#include <string>
14
15
7.31k
#define ENOUGH_DATA_THRESHOLD 256
16
17
namespace kencodingprober
18
{
19
class KCODECS_NO_EXPORT CharDistributionAnalysis
20
{
21
public:
22
32.5k
    CharDistributionAnalysis() = default;
23
32.5k
    virtual ~CharDistributionAnalysis() = default;
24
25
    // Feed a character with known length
26
    void HandleOneChar(const char *aStr, unsigned int aCharLen)
27
13.3M
    {
28
        // we only care about 2-bytes character in our distribution analysis
29
13.3M
        const int code = (aCharLen == 2) ? GetCode(reinterpret_cast<const uint8_t *>(aStr)) : -1;
30
31
13.3M
        if (code >= 0) {
32
10.8M
            mTotalChars++;
33
            // code is valid
34
10.8M
            if ((unsigned int)code < mTableSize) {
35
3.42M
                if (mCharToFreqOrder[code] < 512) {
36
1.53M
                    mFreqChars++;
37
1.53M
                }
38
3.42M
            }
39
10.8M
        }
40
13.3M
    }
41
42
    // return confidence base on existing data
43
    float GetConfidence();
44
45
    std::string StatusOutput();
46
47
    // It is not necessary to receive all data to draw conclusion. For charset detection,
48
    // certain amount of data is enough
49
    bool GotEnoughData()
50
7.31k
    {
51
7.31k
        return mTotalChars > ENOUGH_DATA_THRESHOLD;
52
7.31k
    }
53
54
protected:
55
    // Characters are not handled based on its original encoded value, but
56
    // converted to an encoding specific unique code.
57
    // This allows multiple encoding formats (e.g. SJIS and EUCJP) of an
58
    // encoding (like JIS X 213) to share one frequency table, mapping this
59
    // code to its frequency.
60
    virtual int GetCode(const uint8_t str[2]) = 0;
61
62
    // The number of characters whose frequency order is less than 512
63
    unsigned int mFreqChars = 0;
64
65
    // Total character encountered.
66
    unsigned int mTotalChars = 0;
67
68
    // Mapping table to get frequency order from code (from GetCode())
69
    const short *mCharToFreqOrder = nullptr;
70
71
    // Size of above table
72
    unsigned int mTableSize = 0;
73
74
    // This is a constant value varies from language to language, it is used in
75
    // calculating confidence. See my paper for further detail.
76
    float mTypicalDistributionRatio = 0.0f;
77
};
78
79
class KCODECS_NO_EXPORT EUCKRDistributionAnalysis : public CharDistributionAnalysis
80
{
81
public:
82
    EUCKRDistributionAnalysis();
83
84
protected:
85
    // for euc-KR encoding, we are interested
86
    //  first  byte range: 0xb0 -- 0xfe
87
    //  second byte range: 0xa1 -- 0xfe
88
    // no validation needed here. State machine has done that
89
    int GetCode(const uint8_t str[2]) override
90
2.19M
    {
91
2.19M
        if (str[0] >= 0xb0) {
92
2.05M
            return 94 * (str[0] - 0xb0) + str[1] - 0xa1;
93
2.05M
        } else {
94
134k
            return -1;
95
134k
        }
96
2.19M
    }
97
};
98
99
class KCODECS_NO_EXPORT GB2312DistributionAnalysis : public CharDistributionAnalysis
100
{
101
public:
102
    GB2312DistributionAnalysis();
103
104
protected:
105
    // for GB2312 encoding, we are interested
106
    //  first  byte range: 0xb0 -- 0xfe
107
    //  second byte range: 0xa1 -- 0xfe
108
    // no validation needed here. State machine has done that
109
    int GetCode(const uint8_t str[2]) override
110
3.37M
    {
111
3.37M
        if (str[0] >= 0xb0 && str[1] >= 0xa1) {
112
3.22M
            return 94 * (str[0] - 0xb0) + str[1] - 0xa1;
113
3.22M
        } else {
114
154k
            return -1;
115
154k
        }
116
3.37M
    }
117
};
118
119
class KCODECS_NO_EXPORT Big5DistributionAnalysis : public CharDistributionAnalysis
120
{
121
public:
122
    Big5DistributionAnalysis();
123
124
protected:
125
    // for big5 encoding, we are interested
126
    //  first  byte range: 0xa4 -- 0xfe
127
    //  second byte range: 0x40 -- 0x7e , 0xa1 -- 0xfe
128
    // no validation needed here. State machine has done that
129
    int GetCode(const uint8_t str[2]) override
130
2.46M
    {
131
2.46M
        if (str[0] >= 0xa4)
132
2.46M
            if (str[1] >= 0xa1) {
133
2.45M
                return 157 * (str[0] - 0xa4) + str[1] - 0xa1 + 63;
134
2.45M
            } else {
135
1.26k
                return 157 * (str[0] - 0xa4) + str[1] - 0x40;
136
1.26k
            }
137
3.87k
        else {
138
3.87k
            return -1;
139
3.87k
        }
140
2.46M
    }
141
};
142
143
class KCODECS_NO_EXPORT SJISDistributionAnalysis : public CharDistributionAnalysis
144
{
145
public:
146
    SJISDistributionAnalysis();
147
148
protected:
149
    // for sjis encoding, we are interested
150
    //  first  byte range: 0x81 -- 0x9f , 0xe0 -- 0xfe
151
    //  second byte range: 0x40 -- 0x7e,  0x81 -- oxfe
152
    // no validation needed here. State machine has done that
153
    int GetCode(const uint8_t str[2]) override
154
349k
    {
155
349k
        int code;
156
349k
        if (str[0] >= 0x81 && *str <= 0x9f) {
157
317k
            code = 188 * (str[0] - 0x81);
158
317k
        } else if (str[0] >= 0xe0 && str[0] <= 0xef) {
159
31.1k
            code = 188 * (str[0] - 0xe0 + 31);
160
31.1k
        } else {
161
537
            return -1;
162
537
        }
163
348k
        code += str[1] - 0x40;
164
348k
        if (str[1] > 0x7f) {
165
347k
            code--;
166
347k
        }
167
348k
        return code;
168
349k
    }
169
};
170
171
class KCODECS_NO_EXPORT EUCJPDistributionAnalysis : public CharDistributionAnalysis
172
{
173
public:
174
    EUCJPDistributionAnalysis();
175
176
protected:
177
    // for euc-JP encoding, we are interested
178
    //  first  byte range: 0xa0 -- 0xfe
179
    //  second byte range: 0xa1 -- 0xfe
180
    // no validation needed here. State machine has done that
181
    int GetCode(const uint8_t str[2]) override
182
2.75M
    {
183
2.75M
        if (str[0] >= 0xa0) {
184
2.75M
            return 94 * (str[0] - 0xa1) + str[1] - 0xa1;
185
2.75M
        } else {
186
356
            return -1;
187
356
        }
188
2.75M
    }
189
};
190
}
191
#endif // CharDistribution_h__