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 | with
Ada.IO_Exceptions,
Ada.Strings.Fixed;
package body CSV is
use Ada.Strings.Fixed;
----------------
-- Get_Bounds --
----------------
function Get_Bounds (Item : String; Separator : Character := ',') return Fields_Bounds is
In_Quotes : Boolean := False;
begin
for I in Item'Range loop
if Item (I) = '"' then
In_Quotes := not In_Quotes;
elsif not In_Quotes and Item (I) = Separator then
return Bounds'(Item'First, I - 1) & Get_Bounds (Item (I + 1 .. Item'Last), Separator);
end if;
end loop;
return (1 => (Item'First, Item'Last));
end Get_Bounds;
-------------
-- Extract --
-------------
function Extract
(Item : String;
Fields : Fields_Bounds;
Column : Positive;
Do_Unquote : Boolean := True)
return String
is
Extracted : constant String :=
Item (Fields (Column).Start .. Fields (Column).Stop);
begin
if Do_Unquote then
return CSV.Unquote (Extracted);
else
return Extracted;
end if;
end Extract;
-----------
-- Quote --
-----------
function Quote (Item : String) return String is
Result : String (Item'First .. Item'Last + Count (Item, """") + 2);
Current_Index : Positive;
begin
Current_Index := Result'First;
Result (Current_Index) := '"';
for I in Item'Range loop
if Item (I) = '"' then
Current_Index := Current_Index + 1;
Result (Current_Index) := '"';
end if;
Current_Index := Current_Index + 1;
Result (Current_Index) := Item (I);
end loop;
Result (Result'Last) := '"';
return Result;
end Quote;
-------------
-- Unquote --
-------------
function Unquote (Item : String) return String is
use Ada.IO_Exceptions;
Result : String (Item'Range);
Index_In : Positive;
Index_Out : Natural;
begin
if Item = "" or else Item (Item'First) /= '"' then
return Item;
end if;
Index_In := Item'First + 1;
Index_Out := Result'First - 1;
while Index_In <= Item'Last - 1 loop
if Item (Index_In) = '"' then
Index_Out := Index_Out + 1;
Result (Index_Out) := '"';
if Item (Index_In + 1) = '"' then
Index_In := Index_In + 1;
end if;
else
Index_Out := Index_Out + 1;
Result (Index_Out) := Item (Index_In);
end if;
Index_In := Index_In + 1;
end loop;
if Item (Item'Last) /= '"' then
raise End_Error with "Last character to unquote is not a "" in [" & Item & ']';
end if;
return Result (Result'First .. Index_Out);
end Unquote;
-------------
-- Unquote --
-------------
function Unquote (Item : String; Slice : Bounds; Size : Natural := 0) return String is
use Ada.Strings;
Raw_Line : constant String := Unquote (Item (Slice.Start .. Slice.Stop));
begin
if Size = 0 then
return Trim (Raw_Line, Both);
elsif Raw_Line'Length < Size then
return Raw_Line & (Size - Raw_Line'Length) * ' ';
else
return Raw_Line (Raw_Line'First .. Raw_Line'First + Size - 1);
end if;
end Unquote;
end CSV;
|