1with
2  Ada.IO_Exceptions,
3  Ada.Strings.Fixed;
4package body CSV is
5   use Ada.Strings.Fixed;
6
7   ----------------
8   -- Get_Bounds --
9   ----------------
10
11   function Get_Bounds (Item : String; Separator : Character := ',') return Fields_Bounds is
12      In_Quotes : Boolean := False;
13   begin
14      for I in Item'Range loop
15         if Item(I) = '"' then
16            In_Quotes := not In_Quotes;
17         elsif not In_Quotes and Item (I) = Separator then
18            return Bounds'(Item'First, I-1) & Get_Bounds (Item (I+1 .. Item'Last), Separator);
19         end if;
20      end loop;
21
22      return (1 => (Item'First, Item'Last));
23   end Get_Bounds;
24
25   -------------
26   -- Extract --
27   -------------
28
29   function Extract (
30      Item   : String;
31      Fields : Fields_Bounds;
32      Column : Positive;
33      Unquote: Boolean:= True
34   )
35   return String
36   is
37      Extracted: constant String:=
38         Item( Fields(Column).Start .. Fields(Column).Stop );
39   begin
40      if Unquote then
41        return CSV.Unquote(Extracted);
42      else
43        return Extracted;
44      end if;
45   end Extract;
46
47   -----------
48   -- Quote --
49   -----------
50
51   function Quote (Item : String) return String is
52      Result : String (Item'First .. Item'Last + Count (Item, """") + 2);
53      Index  : Positive;
54   begin
55      Index := Result'First;
56      Result (Index) := '"';
57
58      for I in Item'Range loop
59         if Item (I) = '"' then
60            Index := Index + 1;
61            Result (Index) := '"';
62         end if;
63         Index := Index + 1;
64         Result (Index) := Item (I);
65      end loop;
66      Result (Result'Last) := '"';
67
68      return Result;
69   end Quote;
70
71   -------------
72   -- Unquote --
73   -------------
74
75   function Unquote (Item : String) return String is
76      use Ada.IO_Exceptions;
77
78      Result    : String(Item'Range);
79      Index_In  : Positive;
80      Index_Out : Natural;
81   begin
82      if Item = "" or else Item (Item'First) /= '"' then
83         return Item;
84      end if;
85
86      Index_In  := Item'First+1;
87      Index_Out := Result'First-1;
88      while Index_In <= Item'Last-1 loop
89         if Item (Index_In) = '"' then
90            Index_Out := Index_Out + 1;
91            Result (Index_Out) := '"';
92            if Item (Index_In+1) ='"' then
93               Index_In := Index_In + 1;
94            end if;
95         else
96            Index_Out := Index_Out + 1;
97            Result (Index_Out) := Item (Index_In);
98         end if;
99         Index_In := Index_In + 1;
100      end loop;
101
102      if Item (Item'Last) /= '"' then
103         raise End_Error;
104      end if;
105
106      return Result (Result'First .. Index_Out);
107   end Unquote;
108
109   -------------
110   -- Unquote --
111   -------------
112
113   function Unquote (Item : String; Slice : Bounds; Size : Natural := 0) return String is
114      use Ada.Strings;
115      Raw_Line : constant String := Unquote (Item (Slice.Start .. Slice.Stop));
116   begin
117      if Size = 0 then
118         return Trim (Raw_Line, Both);
119      elsif Raw_Line'Length < Size then
120         return Raw_Line & (Size - Raw_Line'Length) * ' ';
121      else
122         return Raw_Line (Raw_Line'First .. Raw_Line'First + Size - 1);
123      end if;
124   end Unquote;
125
126end CSV;
127