MCPcopy Create free account
hub / github.com/apache/arrow / gdv_fn_initcap_utf8

Function gdv_fn_initcap_utf8

cpp/src/gandiva/gdv_string_function_stubs.cc:475–567  ·  view source on GitHub ↗

For a given text, initialize the first letter after a word-separator and lowercase the others e.g: - "IT is a tEXt str" -> "It Is A Text Str"

Source from the content-addressed store, hash-verified

473// the others e.g:
474// - "IT is a tEXt str" -> "It Is A Text Str"
475GANDIVA_EXPORT
476const char* gdv_fn_initcap_utf8(int64_t context, const char* data, int32_t data_len,
477 int32_t* out_len) {
478 if (data_len == 0) {
479 *out_len = data_len;
480 return "";
481 }
482
483 // If it is a single-byte character (ASCII), corresponding uppercase is always 1-byte
484 // long; if it is >= 2 bytes long, uppercase can be at most 4 bytes long, so length of
485 // the output can be at most twice the length of the input
486 char* out = reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, 2 * data_len));
487 if (out == nullptr) {
488 gdv_fn_context_set_error_msg(context, "Could not allocate memory for output string");
489 *out_len = 0;
490 return "";
491 }
492
493 int32_t char_len = 0;
494 int32_t out_char_len = 0;
495 int32_t out_idx = 0;
496 uint32_t char_codepoint;
497
498 // Any character is considered as space, except if it is alphanumeric
499 bool last_char_was_space = true;
500
501 for (int32_t i = 0; i < data_len; i += char_len) {
502 // An optimization for single byte characters:
503 if (static_cast<signed char>(data[i]) >= 0) { // 1-byte char (0x00 ~ 0x7F)
504 char_len = 1;
505 char cur = data[i];
506
507 if (cur >= 0x61 && cur <= 0x7a && last_char_was_space) {
508 // Check if the character is the first one of the word and it is
509 // lowercase -> 'a' - 'z' : 0x61 - 0x7a.
510 // Then turn it into uppercase -> 'A' - 'Z' : 0x41 - 0x5a
511 out[out_idx++] = static_cast<char>(cur - 0x20);
512 last_char_was_space = false;
513 } else if (cur >= 0x41 && cur <= 0x5a && !last_char_was_space) {
514 out[out_idx++] = static_cast<char>(cur + 0x20);
515 } else {
516 // Check if the ASCII character is not an alphanumeric character:
517 // '0' - '9': 0x30 - 0x39
518 // 'a' - 'z' : 0x61 - 0x7a
519 // 'A' - 'Z' : 0x41 - 0x5a
520 last_char_was_space = (cur < 0x30) || (cur > 0x39 && cur < 0x41) ||
521 (cur > 0x5a && cur < 0x61) || (cur > 0x7a);
522 out[out_idx++] = cur;
523 }
524 continue;
525 }
526
527 char_len = gdv_fn_utf8_char_length(data[i]);
528
529 // Control reaches here when we encounter a multibyte character
530 const auto* in_char = (const uint8_t*)(data + i);
531
532 // Decode the multibyte character

Callers 1

TESTFunction · 0.85

Calls 7

gdv_fn_utf8_char_lengthFunction · 0.85
UTF8DecodeFunction · 0.85
UTF8EncodeFunction · 0.85

Tested by 1

TESTFunction · 0.68