136 lines
3.4 KiB
Go
136 lines
3.4 KiB
Go
/*
|
|
The functions in this file are unexported to ensure safe use through the Parser.
|
|
*/
|
|
|
|
package libpostal
|
|
|
|
//#cgo LDFLAGS: -lpostal
|
|
//#include <libpostal/libpostal.h>
|
|
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
|
|
}
|