excel_writer_18.0.0_ae0dcf49/extras/csv.adb

  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;