/* The functions in this file are unexported to ensure safe use through the Parser. */ package libpostal //#cgo LDFLAGS: -lpostal //#include import "C" import ( "fmt" "strings" "unsafe" ) func setup() bool { response := C.libpostal_setup() return bool(response) } func setupDataDir(datadir string) bool { datadir_cstr := C.CString(datadir) response := C.libpostal_setup_datadir(datadir_cstr) C.free(unsafe.Pointer(datadir_cstr)) return bool(response) } func tearDown() { C.libpostal_teardown() } func setupParser() bool { response := C.libpostal_setup_parser() return bool(response) } func setupParserDataDir(datadir string) bool { datadir_cstr := C.CString(datadir) response := C.libpostal_setup_parser_datadir(datadir_cstr) C.free(unsafe.Pointer(&datadir_cstr)) return bool(response) } func tearDownParser() { C.libpostal_teardown_parser() } func setupLanguageClassifier() bool { response := C.libpostal_setup_language_classifier() return bool(response) } func setupLanguageClassifierDataDir(datadir string) bool { datadir_cstr := C.CString(datadir) response := C.libpostal_setup_language_classifier_datadir(datadir_cstr) C.free(unsafe.Pointer(datadir_cstr)) return bool(response) } func tearDownLanguageClassifier() { C.libpostal_teardown_language_classifier() } type AddressParserOptions struct { Language string Country string } func (goOpts AddressParserOptions) toC() (C.libpostal_address_parser_options_t, func()) { cOpts := C.libpostal_get_address_parser_default_options() var allocations []unsafe.Pointer if goOpts.Language != "" { cLang := C.CString(goOpts.Language) cOpts.language = cLang allocations = append(allocations, unsafe.Pointer(cLang)) } if goOpts.Country != "" { cCountry := C.CString(goOpts.Country) cOpts.country = cCountry allocations = append(allocations, unsafe.Pointer(cCountry)) } cleanup := func() { for _, ptr := range allocations { C.free(ptr) } } return cOpts, cleanup } func GetDefaultAddressParserOptions() AddressParserOptions { cOpts := C.libpostal_get_address_parser_default_options() return AddressParserOptions{ Language: C.GoString(cOpts.language), Country: C.GoString(cOpts.country), } } func parseAddress(addressToParse string, options AddressParserOptions) (Address, error) { address_cstr := C.CString(addressToParse) defer C.free(unsafe.Pointer(address_cstr)) cOpts, cleanup := options.toC() defer cleanup() var address Address response := C.libpostal_parse_address(address_cstr, cOpts) defer C.libpostal_address_parser_response_destroy(response) labelsSlice := unsafe.Slice(response.labels, int(response.num_components)) componentSlice := unsafe.Slice(response.components, int(response.num_components)) for i := range int(response.num_components) { label := C.GoString(labelsSlice[i]) component := C.GoString(componentSlice[i]) switch label { case "house_number": address.HouseNumber = strings.Clone(component) case "road": address.Road = strings.Clone(component) case "city": address.City = strings.Clone(component) case "state": address.State = strings.Clone(component) case "postcode": address.PostCode = strings.Clone(component) default: return Address{}, fmt.Errorf("unrecognized label: %s (%s)", label, component) } } // is the Address valid? if err := address.Invalid(); err != nil { return Address{}, err } return address, nil }