summaryrefslogtreecommitdiffstats
path: root/app/main.f90
blob: 0029d6e4439b24c0550f771c4a8825bcd8b4fb39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
!> A one-shot command-line front end, useful for confirming that an instance
!> answers: `cepis --base-url http://localhost:8080 01001000`.
program main
    use, intrinsic :: iso_fortran_env, only: real64, output_unit, error_unit
    use cepis
    implicit none

    character(len=:), allocatable :: url, message
    character(len=:), allocatable :: ceps(:)
    type(cepis_client) :: client
    integer :: status
    logical :: want_health

    call parse_arguments(url, ceps, want_health)

    if (len(url) > 0) then
        call cepis_client_init(client, status, message, base_url=url)
    else
        call cepis_client_init(client, status, message)
    end if
    if (status /= CEPIS_OK) then
        write (error_unit, '(A)') 'cepis: '//message
        stop 2
    end if

    if (want_health) then
        call show_health(client)
    else if (size(ceps) == 1) then
        call show_one(client, trim(ceps(1)))
    else
        call show_many(client, ceps)
    end if

contains

    subroutine usage()
        write (error_unit, '(A)') 'usage: cepis [--base-url URL] CEP [CEP ...]'
        write (error_unit, '(A)') '       cepis [--base-url URL] --health'
        stop 2
    end subroutine usage

    subroutine parse_arguments(base, values, health)
        character(len=:), allocatable, intent(out) :: base
        character(len=:), allocatable, intent(out) :: values(:)
        logical, intent(out) :: health
        character(len=4096) :: argument
        character(len=64) :: collected(256)
        integer :: count, i, length, total

        base = ''
        health = .false.
        count = 0
        total = command_argument_count()

        i = 1
        do while (i <= total)
            call get_command_argument(i, argument, length)
            if (argument(1:length) == '--health') then
                health = .true.
            else if (argument(1:length) == '--base-url') then
                i = i + 1
                if (i > total) call usage()
                call get_command_argument(i, argument, length)
                base = argument(1:length)
            else if (argument(1:length) == '--help' .or. argument(1:length) == '-h') then
                call usage()
            else
                if (count >= size(collected)) call usage()
                count = count + 1
                collected(count) = argument(1:min(length, len(collected)))
            end if
            i = i + 1
        end do

        if (.not. health .and. count == 0) call usage()

        allocate (character(len=64) :: values(count))
        do i = 1, count
            values(i) = collected(i)
        end do
    end subroutine parse_arguments

    subroutine show_health(handle)
        type(cepis_client), intent(in) :: handle
        type(cepis_health) :: report
        integer :: code
        character(len=:), allocatable :: detail

        call handle%health(report, code, detail)
        if (code /= CEPIS_OK) then
            write (error_unit, '(A)') 'cepis: '//cepis_status_name(code)//': '//detail
            stop 1
        end if

        write (output_unit, '(A)') 'status         '//report%status
        write (output_unit, '(A)') 'dne            '//report%dne
        write (output_unit, '(A,I0)') 'ceps           ', report%ceps
        write (output_unit, '(A,I0)') 'geo            ', report%geo
        write (output_unit, '(A)') 'base_gerada_em '//report%base_gerada_em
    end subroutine show_health

    subroutine show_one(handle, cep)
        type(cepis_client), intent(in) :: handle
        character(len=*), intent(in) :: cep
        type(cepis_address) :: address
        integer :: code
        character(len=:), allocatable :: detail

        call handle%lookup(cep, address, code, detail)
        if (code /= CEPIS_OK) then
            write (error_unit, '(A)') 'cepis: '//cepis_status_name(code)//': '//detail
            if (address%has_faixa) call show_faixa(address%faixa)
            stop 1
        end if

        write (output_unit, '(A)') 'cep            '//address%formatted_cep()
        write (output_unit, '(A)') 'logradouro     '//address%logradouro
        write (output_unit, '(A)') 'complemento    '//address%complemento
        write (output_unit, '(A)') 'unidade        '//address%unidade
        write (output_unit, '(A)') 'bairro         '//address%bairro
        write (output_unit, '(A)') 'localidade     '//address%localidade
        write (output_unit, '(A)') 'uf             '//address%uf
        write (output_unit, '(A)') 'estado         '//address%estado
        write (output_unit, '(A)') 'regiao         '//address%regiao
        write (output_unit, '(A)') 'ibge           '//address%ibge
        write (output_unit, '(A)') 'gia            '//address%gia
        write (output_unit, '(A)') 'ddd            '//address%ddd
        write (output_unit, '(A)') 'siafi          '//address%siafi
        if (address%has_geo) then
            write (output_unit, '(A,F0.6,A,F0.6,A,I0,A)') 'geo            ', &
                address%geo%lat, ', ', address%geo%lon, ' (', address%geo%raio_m, &
                ' m, '//address%geo%precisao//')'
        end if
    end subroutine show_one

    !> What the API knows about a CEP that does not exist: the municipality it
    !> would have fallen under. The lookup still failed, so this goes to stderr
    !> with the error, and the exit status stays 1.
    subroutine show_faixa(faixa)
        type(cepis_faixa), intent(in) :: faixa

        write (error_unit, '(A)') '  faixa        '//faixa%localidade//'/'// &
            faixa%uf//'  ibge '//faixa%ibge
        write (error_unit, '(A,I0,A)') '  existentes   '//faixa%formatted_cep_ini()// &
            '..'//faixa%formatted_cep_fim()//'  ', faixa%ceps, &
            ' CEPs (the range is sparse; most numbers in it do not exist)'
    end subroutine show_faixa

    subroutine show_many(handle, values)
        type(cepis_client), intent(in) :: handle
        character(len=*), intent(in) :: values(:)
        type(cepis_address), allocatable :: addresses(:)
        integer :: code, i
        character(len=:), allocatable :: detail

        call handle%lookup_many(values, addresses, code, detail)
        if (code /= CEPIS_OK) then
            write (error_unit, '(A)') 'cepis: '//cepis_status_name(code)//': '//detail
            stop 1
        end if

        do i = 1, size(addresses)
            if (addresses(i)%found) then
                write (output_unit, '(A)') trim(values(i))//'  '// &
                    addresses(i)%localidade//'/'//addresses(i)%uf//'  '// &
                    addresses(i)%logradouro
            else
                write (output_unit, '(A)') trim(values(i))//'  not found'
            end if
        end do
    end subroutine show_many

end program main