1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#include "mongo/util/icu.h"
#include <unicode/uchar.h>
#include <unicode/utf8.h>
namespace mongo {
namespace {
int getColumnWidth(UChar32 codepoint, bool ambiguousAsFullWidth) {
const int eaw = u_getIntPropertyValue(codepoint, UCHAR_EAST_ASIAN_WIDTH);
switch (eaw) {
case U_EA_FULLWIDTH:
case U_EA_WIDE:
return 2;
case U_EA_AMBIGUOUS:
if (ambiguousAsFullWidth) {
return 2;
}
[[fallthrough]];
case U_EA_NEUTRAL:
if (u_hasBinaryProperty(codepoint, UCHAR_EMOJI_PRESENTATION)) {
return 2;
}
[[fallthrough]];
case U_EA_HALFWIDTH:
case U_EA_NARROW:
default:
const auto zero_width_mask = U_GC_CC_MASK | // C0/C1 control code
U_GC_CF_MASK | // Format control character
U_GC_ME_MASK | // Enclosing mark
U_GC_MN_MASK; // Nonspacing mark
if (codepoint != 0x00AD && // SOFT HYPHEN is Cf but not zero-width
((U_MASK(u_charType(codepoint)) & zero_width_mask) ||
u_hasBinaryProperty(codepoint, UCHAR_EMOJI_MODIFIER))) {
return 0;
}
return 1;
}
}
} // namespace
// This is a modified version of GetStringWidth from node. We don't currently support wide strings
// in the test runner, so it has been converted to use the U8 cursor API. For more details on
// string width calculation see: https://www.unicode.org/reports/tr11/
int icuGetStringWidth(StringData value, bool ambiguousAsFullWidth, bool expandEmojiSequence) {
const uint8_t* str = reinterpret_cast<const uint8_t*>(value.data());
UChar32 output = 0;
UChar32 previous;
int offset = 0;
int strLength = static_cast<int>(value.length());
int width = 0;
while (offset < strLength) {
previous = output;
U8_NEXT(str, offset, strLength, output);
if (!expandEmojiSequence && offset > 0 && previous == 0x200d &&
(u_hasBinaryProperty(output, UCHAR_EMOJI_PRESENTATION) ||
u_hasBinaryProperty(output, UCHAR_EMOJI_MODIFIER))) {
continue;
}
width += getColumnWidth(output, ambiguousAsFullWidth);
}
return width;
}
} // namespace mongo
|