/src/kcodecs/src/probers/nsLatin1Prober.cpp
Line | Count | Source |
1 | | /* -*- C++ -*- |
2 | | SPDX-FileCopyrightText: 1998 Netscape Communications Corporation <developer@mozilla.org> |
3 | | |
4 | | SPDX-License-Identifier: MIT |
5 | | */ |
6 | | |
7 | | #include "nsLatin1Prober.h" |
8 | | |
9 | | #include <format> |
10 | | #include <numeric> |
11 | | |
12 | | #define UDF 0 // undefined |
13 | 4.39k | #define OTH 1 // other |
14 | | #define ASC 2 // ascii capital letter |
15 | | #define ASS 3 // ascii small letter |
16 | | #define ACV 4 // accent capital vowel |
17 | | #define ACO 5 // accent capital other |
18 | | #define ASV 6 // accent small vowel |
19 | | #define ASO 7 // accent small other |
20 | 37.9M | #define CLASS_NUM 8 // total classes |
21 | | |
22 | | namespace kencodingprober |
23 | | { |
24 | | static const unsigned char Latin1_CharToClass[] = { |
25 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // 00 - 07 |
26 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // 08 - 0F |
27 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // 10 - 17 |
28 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // 18 - 1F |
29 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // 20 - 27 |
30 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // 28 - 2F |
31 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // 30 - 37 |
32 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // 38 - 3F |
33 | | OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC, // 40 - 47 |
34 | | ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, // 48 - 4F |
35 | | ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, // 50 - 57 |
36 | | ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH, // 58 - 5F |
37 | | OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS, // 60 - 67 |
38 | | ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, // 68 - 6F |
39 | | ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, // 70 - 77 |
40 | | ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH, // 78 - 7F |
41 | | OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH, // 80 - 87 |
42 | | OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF, // 88 - 8F |
43 | | UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // 90 - 97 |
44 | | OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO, // 98 - 9F |
45 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // A0 - A7 |
46 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // A8 - AF |
47 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // B0 - B7 |
48 | | OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, // B8 - BF |
49 | | ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO, // C0 - C7 |
50 | | ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV, // C8 - CF |
51 | | ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH, // D0 - D7 |
52 | | ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO, // D8 - DF |
53 | | ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO, // E0 - E7 |
54 | | ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV, // E8 - EF |
55 | | ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH, // F0 - F7 |
56 | | ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO, // F8 - FF |
57 | | }; |
58 | | |
59 | | /* 0 : illegal |
60 | | 1 : very unlikely |
61 | | 2 : normal |
62 | | 3 : very likely |
63 | | */ |
64 | | static const unsigned char Latin1ClassModel[] = { |
65 | | /* UDF OTH ASC ASS ACV ACO ASV ASO */ |
66 | | /*UDF*/ 0, 0, 0, 0, 0, 0, 0, 0, |
67 | | /*OTH*/ 0, 3, 3, 3, 3, 3, 3, 3, |
68 | | /*ASC*/ 0, 3, 3, 3, 3, 3, 3, 3, |
69 | | /*ASS*/ 0, 3, 3, 3, 1, 1, 3, 3, |
70 | | /*ACV*/ 0, 3, 3, 3, 1, 2, 1, 2, |
71 | | /*ACO*/ 0, 3, 3, 3, 3, 3, 3, 3, |
72 | | /*ASV*/ 0, 3, 1, 3, 1, 1, 1, 3, |
73 | | /*ASO*/ 0, 3, 1, 3, 1, 1, 3, 3, |
74 | | }; |
75 | | |
76 | | nsLatin1Prober::nsLatin1Prober() |
77 | 4.39k | : mLastCharClass(OTH) |
78 | 4.39k | { |
79 | 4.39k | } |
80 | | |
81 | | nsProbingState nsLatin1Prober::HandleData(const char *aBuf, unsigned int aLen) |
82 | 4.39k | { |
83 | 4.39k | char *newBuf1 = nullptr; |
84 | 4.39k | unsigned int newLen1 = 0; |
85 | | |
86 | 4.39k | if (!FilterWithEnglishLetters(aBuf, aLen, &newBuf1, newLen1)) { |
87 | 0 | newBuf1 = (char *)aBuf; |
88 | 0 | newLen1 = aLen; |
89 | 0 | } |
90 | | |
91 | 37.9M | for (unsigned int i = 0; i < newLen1; i++) { |
92 | 37.9M | const unsigned char charClass = Latin1_CharToClass[(unsigned char)newBuf1[i]]; |
93 | 37.9M | const unsigned char freq = Latin1ClassModel[mLastCharClass * CLASS_NUM + charClass]; |
94 | 37.9M | if (freq == 0) { |
95 | 488 | mState = eNotMe; |
96 | 488 | break; |
97 | 488 | } |
98 | 37.9M | mFreqCounter[freq]++; |
99 | 37.9M | mLastCharClass = charClass; |
100 | 37.9M | } |
101 | | |
102 | 4.39k | if (newBuf1 != aBuf) { |
103 | 4.39k | free(newBuf1); |
104 | 4.39k | } |
105 | | |
106 | 4.39k | return mState; |
107 | 4.39k | } |
108 | | |
109 | | float nsLatin1Prober::GetConfidence(void) |
110 | 11.0k | { |
111 | 11.0k | if (mState == eNotMe) { |
112 | 1.20k | return 0.01f; |
113 | 1.20k | } |
114 | | |
115 | 9.84k | float confidence; |
116 | 9.84k | const auto total = std::accumulate(mFreqCounter.begin(), mFreqCounter.end(), 0ul); |
117 | | |
118 | 9.84k | if (!total) { |
119 | 1.61k | confidence = 0.0f; |
120 | 8.22k | } else { |
121 | 8.22k | confidence = mFreqCounter[3] * 1.0f / total; |
122 | 8.22k | confidence -= mFreqCounter[1] * 20.0f / total; |
123 | 8.22k | } |
124 | | |
125 | 9.84k | if (confidence < 0.0f) { |
126 | 1.86k | confidence = 0.0f; |
127 | 1.86k | } |
128 | | |
129 | | // lower the confidence of latin1 so that other more accurate detector |
130 | | // can take priority. |
131 | 9.84k | confidence *= 0.50f; |
132 | | |
133 | 9.84k | return confidence; |
134 | 11.0k | } |
135 | | |
136 | | std::string nsLatin1Prober::StatusOutput(uint8_t /* indent */) |
137 | 0 | { |
138 | 0 | return std::format( // |
139 | 0 | "{:1.3f} [{}] [{} {} {} {}]", |
140 | 0 | GetConfidence(), |
141 | 0 | GetCharSetName(), |
142 | 0 | mFreqCounter[0], |
143 | 0 | mFreqCounter[1], |
144 | 0 | mFreqCounter[2], |
145 | 0 | mFreqCounter[3]); |
146 | 0 | } |
147 | | } |