Datum postal_normalize(PG_FUNCTION_ARGS) { text *address = PG_GETARG_TEXT_P(0); size_t arr_nelems, i; libpostal_normalize_options_t options = libpostal_get_default_options(); char **expansions = libpostal_expand_address(text_to_cstring(address), options, &arr_nelems); ArrayType *arr; Datum *arr_elems = palloc(sizeof(Datum) * arr_nelems); Oid elem_type = TEXTOID; int16 elem_len; char elem_byval; char elem_align; get_typlenbyvalalign(elem_type, &elem_len, &elem_byval, &elem_align); for (i = 0; i < arr_nelems; i++) { arr_elems[i] = PointerGetDatum(cstring_to_text(expansions[i])); } /* Array construction takes a full copy of the input */ arr = construct_array(arr_elems, arr_nelems, elem_type, elem_len, elem_byval, elem_align); /* Clean up unmanaged memory */ libpostal_expansion_array_destroy(expansions, arr_nelems); PG_RETURN_ARRAYTYPE_P(arr); }
JNIEXPORT jobjectArray JNICALL Java_com_mapzen_jpostal_AddressExpander_libpostalExpand (JNIEnv *env, jclass cls, jstring jAddress, jobject jOptions) { const char *address = (*env)->GetStringUTFChars(env, jAddress, 0); size_t num_expansions = 0; libpostal_normalize_options_t options = libpostal_get_default_options(); jfieldID fid; jclass optionsCls = (*env)->GetObjectClass(env, jOptions); fid = (*env)->GetFieldID(env, optionsCls, "languages", "[Ljava/lang/String;"); if (fid == 0) { return NULL; } jobject jLanguages = (*env)->GetObjectField(env, jOptions, fid); size_t num_languages = 0; char **languages = NULL; int i; if (jLanguages != NULL) { jsize jNumLanguages = (*env)->GetArrayLength(env, jLanguages); languages = malloc(sizeof(char *) * jNumLanguages); jboolean is_copy = JNI_FALSE; num_languages = (size_t)jNumLanguages; for (i = 0; i < jNumLanguages; i++) { jstring jLanguage = (*env)->GetObjectArrayElement(env, jLanguages, i); const char *lang = (*env)->GetStringUTFChars(env, jLanguage, &is_copy); char *language = strdup(lang); languages[i] = language; (*env)->ReleaseStringUTFChars(env, jLanguage, lang); } options.languages = languages; options.num_languages = num_languages; } fid = (*env)->GetFieldID(env, optionsCls, "addressComponents", "S"); if (fid == 0) { return NULL; } options.address_components = (uint16_t) (*env)->GetShortField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "latinAscii", "Z"); if (fid == 0) { return NULL; } options.latin_ascii = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "transliterate", "Z"); if (fid == 0) { return NULL; } options.transliterate = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "stripAccents", "Z"); if (fid == 0) { return NULL; } options.strip_accents = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "decompose", "Z"); if (fid == 0) { return NULL; } options.decompose = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "lowercase", "Z"); if (fid == 0) { return NULL; } options.lowercase = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "trimString", "Z"); if (fid == 0) { return NULL; } options.trim_string = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "dropParentheticals", "Z"); if (fid == 0) { return NULL; } options.drop_parentheticals = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "replaceNumericHyphens", "Z"); if (fid == 0) { return NULL; } options.replace_numeric_hyphens = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "deleteNumericHyphens", "Z"); if (fid == 0) { return NULL; } options.delete_numeric_hyphens = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "splitAlphaFromNumeric", "Z"); if (fid == 0) { return NULL; } options.split_alpha_from_numeric = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "replaceWordHyphens", "Z"); if (fid == 0) { return NULL; } options.replace_word_hyphens = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "deleteWordHyphens", "Z"); if (fid == 0) { return NULL; } options.delete_word_hyphens = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "deleteFinalPeriods", "Z"); if (fid == 0) { return NULL; } options.delete_final_periods = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "deleteAcronymPeriods", "Z"); if (fid == 0) { return NULL; } options.delete_acronym_periods = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "dropEnglishPossessives", "Z"); if (fid == 0) { return NULL; } options.drop_english_possessives = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "deleteApostrophes", "Z"); if (fid == 0) { return NULL; } options.delete_apostrophes = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "expandNumex", "Z"); if (fid == 0) { return NULL; } options.expand_numex = (*env)->GetBooleanField(env, jOptions, fid); fid = (*env)->GetFieldID(env, optionsCls, "romanNumerals", "Z"); if (fid == 0) { return NULL; } options.roman_numerals = (*env)->GetBooleanField(env, jOptions, fid); char **expansions = libpostal_expand_address((char *)address, options, &num_expansions); (*env)->ReleaseStringUTFChars(env, jAddress, address); jobjectArray ret = (jobjectArray)(*env)->NewObjectArray(env, num_expansions, (*env)->FindClass(env, "java/lang/String"), (*env)->NewStringUTF(env, "")); if (num_expansions > 0) { for (size_t i = 0; i < num_expansions; i++) { (*env)->SetObjectArrayElement(env, ret, i, (*env)->NewStringUTF(env, expansions[i])); } } if (expansions != NULL) { libpostal_expansion_array_destroy(expansions, num_expansions); } if (languages != NULL) { for (i = 0; i < num_languages; i++) { free(languages[i]); } free(languages); } return ret; }