Returns the soundex code for a given string The soundex function evaluates expression and returns the most significant letter in the input string followed by a phonetic code. Characters that are not alphabetic are ignored. If expression evaluates to the null value, null is returned. The soundex algorithm works with the following steps: 1. Retain the first letter of the string and drop all other
| 2959 | // numbers, append with zeros until there are three numbers. If you have four or more |
| 2960 | // numbers, retain only the first three. |
| 2961 | FORCE_INLINE |
| 2962 | const char* soundex_utf8(gdv_int64 context, const char* in, gdv_int32 in_len, |
| 2963 | bool in_validity, bool* out_valid, int32_t* out_len) { |
| 2964 | if (in_len <= 0) { |
| 2965 | *out_valid = true; |
| 2966 | *out_len = 0; |
| 2967 | return ""; |
| 2968 | } |
| 2969 | |
| 2970 | // The soundex code is composed by one letter and three numbers |
| 2971 | char* soundex = reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, in_len)); |
| 2972 | char* ret = reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, 4)); |
| 2973 | |
| 2974 | if (soundex == nullptr || ret == nullptr) { |
| 2975 | gdv_fn_context_set_error_msg(context, "Could not allocate memory for output string"); |
| 2976 | *out_valid = false; |
| 2977 | *out_len = 0; |
| 2978 | return ""; |
| 2979 | } |
| 2980 | |
| 2981 | int si = 1; |
| 2982 | int ret_len = 1; |
| 2983 | unsigned char c; |
| 2984 | |
| 2985 | int start_idx = 0; |
| 2986 | for (int i = 0; i < in_len; ++i) { |
| 2987 | if (isalpha(in[i]) > 0) { |
| 2988 | // Retain the first letter |
| 2989 | ret[0] = toupper(in[i]); |
| 2990 | start_idx = i + 1; |
| 2991 | break; |
| 2992 | } |
| 2993 | } |
| 2994 | |
| 2995 | // If ret[0] is not initialised, return validity false |
| 2996 | if (start_idx == 0) { |
| 2997 | *out_valid = false; |
| 2998 | *out_len = 0; |
| 2999 | return ""; |
| 3000 | } |
| 3001 | |
| 3002 | soundex[0] = '\0'; |
| 3003 | // Replace consonants with digits and special letters with 0 |
| 3004 | for (int i = start_idx; i < in_len; i++) { |
| 3005 | if (isalpha(in[i]) > 0) { |
| 3006 | c = toupper(in[i]) - 65; |
| 3007 | if (mappings[c] != soundex[si - 1]) { |
| 3008 | soundex[si] = mappings[c]; |
| 3009 | si++; |
| 3010 | } |
| 3011 | } |
| 3012 | } |
| 3013 | |
| 3014 | int i = 1; |
| 3015 | // If the saved letter's digit is the same as the resulting first digit, skip it |
| 3016 | if (si > 1) { |
| 3017 | if (soundex[1] == mappings[ret[0] - 65]) { |
| 3018 | i = 2; |