summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--makefile3
-rw-r--r--src/candidates.adb45
-rw-r--r--src/candidates.ads75
-rw-r--r--src/csv.adb196
-rw-r--r--src/csv.ads35
-rw-r--r--src/stv.adb32
6 files changed, 386 insertions, 0 deletions
diff --git a/makefile b/makefile
index 9475db8..281f11a 100644
--- a/makefile
+++ b/makefile
@@ -9,3 +9,6 @@ stv:
-hidir build -stubdir build -dumpdir build -o bin/stv
+ada:
+ gnatmake src/stv.adb -Isrc -D build -o bin/adastv
+
diff --git a/src/candidates.adb b/src/candidates.adb
new file mode 100644
index 0000000..3701ffc
--- /dev/null
+++ b/src/candidates.adb
@@ -0,0 +1,45 @@
+
+
+with Ada.Text_IO;
+use Ada.Text_IO;
+with CSV;
+
+
+package body Candidates is
+
+
+ procedure Read_Candidates
+ (Data_File, State : in String;
+ Above_Ballot : out Above_Line_Ballot;
+ Below_Ballot : out Below_Line_Ballot;
+ Candidate_List : out Candidate_Vectors.Vector)
+ is
+ begin
+ end Read_Candidate;
+
+
+
+
+ function Lookup
+ (Above_Ballot : in Above_Line_Ballot;
+ Index : in Natural)
+ return CandidateID_Vectors.Vector is
+ begin
+ return Above_Ballot.Element (Index);
+ end Lookup;
+
+
+
+
+ function Lookup
+ (Below_Ballot : in Below_Line_Ballot;
+ Index : in Natural)
+ return CandidateID is
+ begin
+ return Below_Ballot.Element (Index);
+ end Lookup;
+
+
+end Candidates;
+
+
diff --git a/src/candidates.ads b/src/candidates.ads
new file mode 100644
index 0000000..90b2425
--- /dev/null
+++ b/src/candidates.ads
@@ -0,0 +1,75 @@
+
+
+with Ada.Containers.Vectors;
+
+
+package Candidates is
+
+
+ type Candidate is private;
+ type CandidateID is Natural;
+
+
+ type Above_Line_Ballot is private;
+ type Below_Line_Ballot is private;
+
+
+ package Candidate_Vectors is new Ada.Containers.Vectors
+ (Index_Type => CandidateID,
+ Element_Type => Candidate);
+
+
+ package CandidateID_Vectors is new Ada.Containers.Vectors
+ (Index_Type => Natural,
+ Element_Type => CandidateID);
+
+
+ procedure Read_Candidates
+ (Data_File, State : in String;
+ Above_Ballot : out Above_Line_Ballot;
+ Below_Ballot : out Below_Line_Ballot;
+ Candidate_List : out Candidate_Vectors.Vector);
+
+
+ function Lookup
+ (Above_Ballot : in Above_Line_Ballot;
+ Index : in Natural)
+ return CandidateID_Vectors.Vector;
+
+
+ function Lookup
+ (Below_Ballot : in Below_Line_Ballot;
+ Index : in Natural)
+ return CandidateID;
+
+
+private
+
+
+ type Candidate is record
+ ID : CandidateID;
+ First_Name : String;
+ Last_Name : String;
+ Group : String;
+ Group_Rank : Natural;
+ Party : String;
+ end record;
+
+
+ package Above_Line_Ballots is new Ada.Containers.Vectors
+ (Index_Type => Natural,
+ Element_Type => CandidateID_Vectors.Vector);
+
+
+ package Below_Line_Ballots is new Ada.Containers.Vectors
+ (Index_Type => Natural,
+ Element_Type => CandidateID);
+
+
+ type Above_Line_Ballot is Above_Line_Ballots.Vector;
+ type Below_Line_Ballot is Below_Line_Ballots.Vector;
+
+
+end Candidates;
+
+
diff --git a/src/csv.adb b/src/csv.adb
new file mode 100644
index 0000000..eab633b
--- /dev/null
+++ b/src/csv.adb
@@ -0,0 +1,196 @@
+
+
+package body CSV is
+
+
+ package SU renames Ada.Strings.Unbounded;
+
+
+
+
+ function Quoted
+ (Input : in SU.Unbounded_String;
+ Output : out SU.Unbounded_String;
+ Remaining : out SU.Unbounded_String)
+ return Boolean
+ is
+ Result : SU.Unbounded_String;
+ This_In : SU.Unbounded_String;
+ begin
+ if SU.Length (Input) > 0 and then
+ SU.Element (Input, 1) = Quote
+ then
+ Result := SU.To_Unbounded_String (0);
+ This_In := SU.Tail (Input, SU.Length (Input) - 1);
+ while SU.Length (This_In) > 0 loop
+ SU.Append (Result, SU.Head (This_In, 1));
+ This_In := SU.Tail (This_In, SU.Length (This_In) - 1);
+ exit when SU.Length (This_In) > 0 and then SU.Element (This_In, 1) = Quote;
+ end loop;
+ Output := Result;
+ Remaining := SU.Tail (This_In, SU.Length (This_In) - 1);
+ return True;
+ else
+ return False;
+ end if;
+ end Quoted;
+
+
+
+
+ function Escape_Char
+ (Input : in SU.Unbounded_String;
+ Output : out SU.Unbounded_String;
+ Remaining : out SU.Unbounded_String)
+ return Boolean is
+ begin
+ if SU.Length (Input) > 1 and then
+ SU.Element (Input, 1) = Escape
+ then
+ Output := SU.Unbounded_Slice (Input, 2, 1);
+ Remaining := SU.Tail (Input, SU.Length (Input) - 2);
+ return True;
+ else
+ return False;
+ end if;
+ end Escape_Char;
+
+
+
+
+ function Field_Char
+ (Input : in SU.Unbounded_String;
+ Output : out SU.Unbounded_String;
+ Remaining : out SU.Unbounded_String)
+ return Boolean is
+ begin
+ if SU.Length (Input) > 0 and then
+ SU.Element (Input, 1) /= Delimiter and then
+ SU.Element (Input, 1) /= Quote and then
+ SU.Element (Input, 1) /= Escape
+ then
+ Output := SU.Head (Input, 1);
+ Remaining := SU.Tail (Input, SU.Length (Input) - 1);
+ return True;
+ else
+ return False;
+ end if;
+ end Field_Char;
+
+
+
+
+ procedure Field
+ (Input : in SU.Unbounded_String;
+ Output : out SU.Unbounded_String;
+ Remaining : out SU.Unbounded_String)
+ is
+ Result : SU.Unbounded_String;
+ This_In, This_Out, This_Remaining : SU.Unbounded_String;
+ begin
+ Result := SU.To_Unbounded_String (0);
+ This_In := Input;
+ while
+ Field_Char (This_In, This_Out, This_Remaining) or else
+ Escape_Char (This_In, This_Out, This_Remaining) or else
+ Quoted (This_In, This_Out, This_Remaining)
+ loop
+ SU.Append (Result, This_Out);
+ This_In := This_Remaining;
+ end loop;
+ Output := Result;
+ Remaining := This_In;
+ end Field;
+
+
+
+
+ function Separator
+ (Input : in SU.Unbounded_String;
+ Output : out SU.Unbounded_String;
+ Remaining : out SU.Unbounded_String)
+ return Boolean is
+ begin
+ if SU.Length (Input) > 0 and then
+ SU.Element (Input, 1) = Delimiter
+ then
+ Output := SU.Head (Input, 1);
+ Remaining := SU.Tail (Input, SU.Length (Input) - 1);
+ return True;
+ else
+ return False;
+ end if;
+ end Separator;
+
+
+
+
+ function Parse_Line
+ (Input : in String)
+ return CSV_Record
+ is
+ Result : CSV_Record := String_Vectors.Empty_Vector;
+ This_In, This_Out, This_Remaining : SU.Unbounded_String;
+ begin
+ This_In := SU.To_Unbounded_String (Input);
+ loop
+ Field (This_In, This_Out, This_Remaining);
+ Result.Append (This_Out);
+ This_In := This_Remaining;
+ exit when not Separator (This_In, This_Out, This_Remaining);
+ This_In := This_Remaining;
+ end loop;
+ return Result;
+ end Parse_Line;
+
+
+
+
+ function Encode_String
+ (Input : in SU.Unbounded_String)
+ return SU.Unbounded_String
+ is
+ Result : SU.Unbounded_String;
+ Elem : Character;
+ Needs_Quotes : Boolean := False;
+ begin
+ Result := SU.To_Unbounded_String (0);
+ for I in Integer range 1 .. SU.Length (Input) loop
+ Elem := SU.Element (Input, I);
+ if Elem = Quote or
+ Elem = Escape
+ then
+ SU.Append (Result, Escape & Elem);
+ else
+ SU.Append (Result, Elem);
+ end if;
+ if Elem = Delimiter then
+ Needs_Quotes := True;
+ end if;
+ end loop;
+ if Needs_Quotes then
+ Result := Quote & Result & Quote;
+ end if;
+ return Result;
+ end Encode_String;
+
+
+
+
+ function Unparse_Record
+ (Input : in CSV_Record)
+ return String
+ is
+ Result : SU.Unbounded_String;
+ begin
+ Result := SU.To_Unbounded_String (0);
+ for Item of Input loop
+ SU.Append (Result, Encode_String (Item) & Delimiter);
+ end loop;
+ return SU.Slice (Result, 1, SU.Length (Result) - 1);
+ end Unparse_Record;
+
+
+end CSV;
+
+
diff --git a/src/csv.ads b/src/csv.ads
new file mode 100644
index 0000000..a8273f5
--- /dev/null
+++ b/src/csv.ads
@@ -0,0 +1,35 @@
+
+
+with Ada.Strings.Unbounded;
+with Ada.Containers.Vectors;
+use type Ada.Strings.Unbounded.Unbounded_String;
+
+
+generic
+ Delimiter : in Character := ',';
+ Quote : in Character := '"';
+ Escape : in Character := '\';
+package CSV is
+
+
+ package String_Vectors is new Ada.Containers.Vectors
+ (Index_Type => Natural,
+ Element_Type => Ada.Strings.Unbounded.Unbounded_String);
+
+
+ subtype CSV_Record is String_Vectors.Vector;
+
+
+ function Parse_Line
+ (Input : in String)
+ return CSV_Record;
+
+
+ function Unparse_Record
+ (Input : in CSV_Record)
+ return String;
+
+
+end CSV;
+
+
diff --git a/src/stv.adb b/src/stv.adb
new file mode 100644
index 0000000..3297da2
--- /dev/null
+++ b/src/stv.adb
@@ -0,0 +1,32 @@
+
+
+with Ada.Text_IO;
+with Ada.Strings.Unbounded;
+with CSV;
+
+
+procedure STV is
+
+
+ package My_CSV is new CSV;
+
+
+ Result : My_CSV.CSV_Record;
+
+
+begin
+
+
+ Result := My_CSV.Parse_Line ("123,4""56,78""9764,3,""4,5"",");
+
+
+ for Item of Result loop
+ Ada.Text_IO.Put_Line (Ada.Strings.Unbounded.To_String (Item));
+ end loop;
+
+
+ Ada.Text_IO.Put_Line (My_CSV.Unparse_Record (Result));
+
+end STV;
+
+