summaryrefslogtreecommitdiffstats
path: root/src/cepis-csv.cob
blob: 29cc6d2c85cb670c35d0faca6455b6cda4c5ca07 (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
IDENTIFICATION DIVISION.
PROGRAM-ID. CEPIS-CSV-NEXT.

*> ---------------------------------------------------------------------
*> Read one field of an RFC 4180 record.
*>
*>     CALL "CEPIS-CSV-NEXT" USING CSV-TEXT CEPIS-CSV-SCAN
*>
*> Values from the batch endpoint contain commas -- "Rua Um, Dois" is an
*> ordinary street name -- and are then double-quoted with "" for an
*> embedded quote. Splitting on commas would shear those rows in two and
*> shift every column after them, so this walks the quoting properly,
*> newlines inside a quoted value included.
*> ---------------------------------------------------------------------

DATA DIVISION.
WORKING-STORAGE SECTION.
01  WS-C                            PIC X.
01  WS-DOUBLED                      PIC X.
01  CONST-QUOTE                     PIC X VALUE '"'.

LINKAGE SECTION.
01  CSV-TEXT                        PIC X(262144).
COPY "cepis-csv.cpy".

PROCEDURE DIVISION USING CSV-TEXT CEPIS-CSV-SCAN.

MAIN-START.
    MOVE SPACES TO CSV-FIELD
    MOVE 0 TO CSV-FIELD-LEN
    MOVE "N" TO CSV-ROW-END
    MOVE "N" TO CSV-EXHAUSTED

    IF CSV-POS > CSV-LEN
        MOVE "Y" TO CSV-EXHAUSTED
        MOVE "Y" TO CSV-ROW-END
        GOBACK
    END-IF

    IF CSV-TEXT(CSV-POS:1) = CONST-QUOTE
        PERFORM READ-QUOTED
    ELSE
        PERFORM READ-BARE
    END-IF

    PERFORM CLOSE-FIELD
    GOBACK.

*> -------------------------------------------------------------------
READ-QUOTED.
    ADD 1 TO CSV-POS
    PERFORM UNTIL CSV-POS > CSV-LEN
        MOVE CSV-TEXT(CSV-POS:1) TO WS-C
        IF WS-C = CONST-QUOTE
            MOVE "N" TO WS-DOUBLED
            IF CSV-POS < CSV-LEN
                IF CSV-TEXT(CSV-POS + 1:1) = CONST-QUOTE
                    MOVE "Y" TO WS-DOUBLED
                END-IF
            END-IF
            IF WS-DOUBLED = "Y"
                PERFORM APPEND-CHAR
                ADD 2 TO CSV-POS
            ELSE
                ADD 1 TO CSV-POS
                EXIT PERFORM
            END-IF
        ELSE
            PERFORM APPEND-CHAR
            ADD 1 TO CSV-POS
        END-IF
    END-PERFORM
    PERFORM UNTIL CSV-POS > CSV-LEN
        MOVE CSV-TEXT(CSV-POS:1) TO WS-C
        IF WS-C = "," OR WS-C = X"0D" OR WS-C = X"0A"
            EXIT PERFORM
        END-IF
        ADD 1 TO CSV-POS
    END-PERFORM.

*> -------------------------------------------------------------------
READ-BARE.
    PERFORM UNTIL CSV-POS > CSV-LEN
        MOVE CSV-TEXT(CSV-POS:1) TO WS-C
        IF WS-C = "," OR WS-C = X"0D" OR WS-C = X"0A"
            EXIT PERFORM
        END-IF
        PERFORM APPEND-CHAR
        ADD 1 TO CSV-POS
    END-PERFORM.

*> -------------------------------------------------------------------
CLOSE-FIELD.
    IF CSV-POS > CSV-LEN
        MOVE "Y" TO CSV-ROW-END
        EXIT PARAGRAPH
    END-IF
    MOVE CSV-TEXT(CSV-POS:1) TO WS-C
    EVALUATE TRUE
        WHEN WS-C = ","
            ADD 1 TO CSV-POS
        WHEN WS-C = X"0D"
            ADD 1 TO CSV-POS
            IF CSV-POS <= CSV-LEN
                IF CSV-TEXT(CSV-POS:1) = X"0A"
                    ADD 1 TO CSV-POS
                END-IF
            END-IF
            MOVE "Y" TO CSV-ROW-END
        WHEN WS-C = X"0A"
            ADD 1 TO CSV-POS
            MOVE "Y" TO CSV-ROW-END
        WHEN OTHER
            ADD 1 TO CSV-POS
    END-EVALUATE.

*> -------------------------------------------------------------------
APPEND-CHAR.
    IF CSV-FIELD-LEN < 512
        ADD 1 TO CSV-FIELD-LEN
        MOVE WS-C TO CSV-FIELD(CSV-FIELD-LEN:1)
    END-IF.

END PROGRAM CEPIS-CSV-NEXT.