How to conveniently parse a very specific chunk of a plaintext file in Ada?

84 views Asked by At

I'm trying to read a URI Extension Block of a Share from Tahoe-LAFS in Ada. It looks something like this:

codec_name:3:crs,codec_params:11:131073-3-10,crypttext_hash:32:..G.3u1~A..o;.w..k,..3.h....K.gk,crypttext_root_hash:32:.}...I3P..Z...A.....tkq.{..'...G,needed_shares:1:3,num_segments:2:52,segment_size:6:131073,share_root_hash:32:.Q>.hGmr.9^J..........size:7:6694675,tail_codec_params:9:9954-3-10,total_shares:2:10,

Now, I was trying to come up with a solution how to get it into a Record type, but I didn't succeed. I thought of a few:

  1. Get all the values into a Map(String)String and after that cast them into their actual types.
  2. Check for the first component of the value, and process it immediately with a switch case statement
1

There are 1 answers

0
Jeffrey R. Carter On BEST ANSWER

You seem to have a string with the structure

field{,field}

where field is structured

<name>:<length>:<value>

and <value> is <length> characters long. This is easily parsed using Ada.Strings.Fixed.Index from the standard library:

function Parsed (Line : in String) return Whatever is
   Result  : Whatever;
   Start   : Positive := Line'First;
   Colon_1 : Positive; -- Constraint_Error will be raised if a colon is missing
   Colon_2 : Positive;
begin -- Parsed;
   All_Fields : loop
      exit All_Fields when Start > Line'Last;

      Colon_1 := Ada.Strings.Fixed.Index (Line, ":", Start);
      Colon_2 := Ada.Strings.Fixed.Index (Line, ":", Colon_1 + 1);

      One_Field : declare
         Name   : constant String   := Line (Start .. Colon_1 - 1);
         Length : constant Positive := Integer'Value (Line (Colon_1 + 1 .. Colon_2 - 1) );
         Value  : constant String   := Line (Colon_2 + 1 .. Colon_2 + Length);
      begin -- One_Field
         -- Update Result using Name and Value
         Start := Colon_2 + Length + 2;
      end One_Field;
   end loop All_Fields;

   return Result;
end Parsed;