MCPcopy Create free account
hub / github.com/apache/impala / MaskSubStrUtf8

Function MaskSubStrUtf8

be/src/exprs/mask-functions-ir.cc:126–190  ·  view source on GitHub ↗

Mask the substring in range [start, end) of the given string value. Using rules in 'MaskTransform'. Indices are counted in UTF-8 code points.

Source from the content-addressed store, hash-verified

124/// Mask the substring in range [start, end) of the given string value. Using rules in
125/// 'MaskTransform'. Indices are counted in UTF-8 code points.
126static StringVal MaskSubStrUtf8(FunctionContext* ctx, const StringVal& val,
127 int start, int end, int masked_upper_char, int masked_lower_char,
128 int masked_digit_char, int masked_other_char) {
129 DCHECK_GE(start, 0);
130 DCHECK_LT(start, end);
131 DCHECK_LE(end, val.len);
132 const char* p_start = reinterpret_cast<char*>(val.ptr);
133 const char* p_end = p_start + val.len;
134 const char* p = p_start;
135 utf8_codecvt<char>::state_type cvt_state;
136 int char_cnt = 0;
137 // Skip leading 'start' code points. Leading bytes will be copied directly.
138 while (char_cnt < start && p != p_end) {
139 uint32_t codepoint = utf8_codecvt<char>::to_unicode(cvt_state, p, p_end);
140 if (CheckAndWarnCodePoint(ctx, codepoint)) return StringVal::null();
141 ++char_cnt;
142 }
143 // Calculating the result length in bytes.
144 int result_bytes = p - p_start;
145 int leading_bytes = result_bytes;
146 // Collect code points at range [start, end - 1) and mask them.
147 vector<uint32_t> masked_code_points;
148 // Create unicode locale for checking upper/lower cases or digits.
149 static const std::locale& loc = boost::locale::generator()("en_US.UTF-8");
150 // Check facet existence to avoid predicates throws exception.
151 if (!std::has_facet<std::ctype<wchar_t>>(loc)) {
152 ctx->SetError("Cannot mask unicode strings since locale en_US.UTF-8 not found!");
153 return StringVal();
154 }
155 while (char_cnt < end && p != p_end) {
156 // Parse and get the first code point in string range [p, p_end).
157 // 'to_unicode' will update the pointer 'p'.
158 uint32_t codepoint = utf8_codecvt<char>::to_unicode(cvt_state, p, p_end);
159 if (CheckAndWarnCodePoint(ctx, codepoint)) return StringVal::null();
160 codepoint = MaskTransform(codepoint, masked_upper_char, masked_lower_char,
161 masked_digit_char, masked_other_char, &loc);
162 masked_code_points.push_back(codepoint);
163 result_bytes += utf::utf_traits<char>::width(codepoint);
164 ++char_cnt;
165 }
166 // Trailing bytes will be copied directly without masking.
167 int tail_len = p_end - p;
168 result_bytes += tail_len;
169
170 StringVal result(ctx, result_bytes);
171 if (UNLIKELY(result.is_null)) return result;
172 // Copy leading bytes.
173 Ubsan::MemCpy(result.ptr, val.ptr, leading_bytes);
174 // Converting masked code points to UTF-8 encoded bytes.
175 char* ptr = reinterpret_cast<char*>(result.ptr) + leading_bytes;
176 p_end = reinterpret_cast<char*>(result.ptr) + result_bytes;
177 for (uint32_t c : masked_code_points) {
178 uint32_t width = utf8_codecvt<char>::from_unicode(cvt_state, c, ptr, p_end);
179 DCHECK(width != utf::illegal && width != utf::incomplete);
180 ptr += width;
181 DCHECK(ptr <= p_end);
182 }
183 // Copy trailing bytes.

Callers 5

MaskShowFirstNImplFunction · 0.85
MaskShowLastNImplFunction · 0.85
MaskFirstNImplFunction · 0.85
MaskLastNImplFunction · 0.85
MaskImplFunction · 0.85

Calls 6

CheckAndWarnCodePointFunction · 0.85
StringValClass · 0.85
MaskTransformFunction · 0.85
widthFunction · 0.85
push_backMethod · 0.80
SetErrorMethod · 0.45

Tested by

no test coverage detected