-- -- Copyright (C) 2021-2023, AdaCore -- -- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -- with Ada.Integer_Wide_Wide_Text_IO; use Ada.Integer_Wide_Wide_Text_IO; with Ada.Strings; use Ada.Strings; with Ada.Strings.Wide_Wide_Fixed; use Ada.Strings.Wide_Wide_Fixed; with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; with Ada.Unchecked_Conversion; with Ada.Wide_Wide_Text_IO; use Ada.Wide_Wide_Text_IO; with UCD.Characters; with UCD.Properties; with Gen_UCD.Compressed_UTF_8_Data; with Gen_UCD.Generic_Compressed_Stage_Table; package body Gen_UCD.Casing is use type UCD.Code_Point; package Database is type Case_Mapping is (Simple_Lowercase, Simple_Titlecase, Simple_Uppercase, Simple_Case_Folding, NFKC_Casefold, Full_Lowercase, Full_Titlecase, Full_Uppercase, Full_Case_Folding); subtype Simple_Case_Mapping is Case_Mapping range Simple_Lowercase .. NFKC_Casefold; subtype Full_Case_Mapping is Case_Mapping range Full_Lowercase .. Full_Case_Folding; procedure Initialize; procedure Set (Character : UCD.Code_Point; Mapping : Case_Mapping; Data : UCD.Code_Point_Vectors.Vector); procedure Set_Cased (Character : UCD.Code_Point; To : Boolean); procedure Set_Case_Ignorable (Character : UCD.Code_Point; To : Boolean); procedure Set_Final_Sigma_Enter (Character : UCD.Code_Point; To : Boolean); procedure Set_Final_Sigma_Continue (Character : UCD.Code_Point; To : Boolean); procedure Set_After_Soft_Dotted_Enter (Character : UCD.Code_Point; To : Boolean); procedure Set_After_Soft_Dotted_Continue (Character : UCD.Code_Point; To : Boolean); procedure Set_After_I_Enter (Character : UCD.Code_Point; To : Boolean); procedure Set_After_I_Continue (Character : UCD.Code_Point; To : Boolean); procedure Compress; function UTF_8_Data_Index_Last return Gen_UCD.UTF_8_Offset; function UTF_8_Data_Element (Index : Gen_UCD.UTF_8_Offset) return Gen_UCD.UTF_8_Code_Unit; function Mapping_Data_Last return Natural; function Mapping_Data_Element (Offset : Natural) return Unsigned_32; function Mapping_Index_Last (Mapping : Case_Mapping) return Natural; function Mapping_Index_Element (Mapping : Case_Mapping; Offset : Natural) return Natural; function Mapping_Index_Group_Size (Mapping : Case_Mapping) return Natural; procedure Print_Statistics; end Database; ----------- -- Build -- ----------- procedure Build is SUC_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("suc"); SLC_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("slc"); STC_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("stc"); SCF_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("scf"); LC_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("lc"); TC_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("tc"); UC_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("uc"); CF_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("cf"); NFKC_CF_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("NFKC_CF"); Cased_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("Cased"); Cased_Y : constant not null UCD.Properties.Property_Value_Access := UCD.Properties.Resolve (Cased_Property, "Y"); CI_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("CI"); CI_Y : constant not null UCD.Properties.Property_Value_Access := UCD.Properties.Resolve (CI_Property, "Y"); SD_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("SD"); SD_Y : constant not null UCD.Properties.Property_Value_Access := UCD.Properties.Resolve (SD_Property, "Y"); CCC_Property : constant not null UCD.Properties.Property_Access := UCD.Properties.Resolve ("ccc"); CCC_0 : constant not null UCD.Properties.Property_Value_Access := UCD.Properties.Resolve (CCC_Property, "Not_Reordered"); CCC_230 : constant not null UCD.Properties.Property_Value_Access := UCD.Properties.Resolve (CCC_Property, "Above"); begin Put_Line (" ... casing"); Database.Initialize; -- Process properties of each character. Do it in reverse order, it -- produce little bit (around 40 bytes) smaller table. for Code in reverse UCD.Code_Point loop declare use type UCD.Properties.Property_Value_Access; SUC_Value : constant UCD.Properties.Property_Value_Access := UCD.Characters.Get (Code, SUC_Property); SLC_Value : constant UCD.Properties.Property_Value_Access := UCD.Characters.Get (Code, SLC_Property); STC_Value : constant UCD.Properties.Property_Value_Access := UCD.Characters.Get (Code, STC_Property); SCF_Value : constant UCD.Properties.Property_Value_Access := UCD.Characters.Get (Code, SCF_Property); LC_Value : constant UCD.Properties.Property_Value_Access := UCD.Characters.Get (Code, LC_Property); TC_Value : constant UCD.Properties.Property_Value_Access := UCD.Characters.Get (Code, TC_Property); UC_Value : constant UCD.Properties.Property_Value_Access := UCD.Characters.Get (Code, UC_Property); CF_Value : constant UCD.Properties.Property_Value_Access := UCD.Characters.Get (Code, CF_Property); NFKC_CF_Value : constant UCD.Properties.Property_Value_Access := UCD.Characters.Get (Code, NFKC_CF_Property); Cased_Value : constant Boolean := UCD.Characters.Get (Code, Cased_Property) = Cased_Y; CI_Value : constant Boolean := UCD.Characters.Get (Code, CI_Property) = CI_Y; SD_Value : constant Boolean := UCD.Characters.Get (Code, SD_Property) = SD_Y; CCC_0_Value : constant Boolean := UCD.Characters.Get (Code, CCC_Property) = CCC_0; CCC_230_Value : constant Boolean := UCD.Characters.Get (Code, CCC_Property) = CCC_230; begin if SUC_Value /= null then Database.Set (Code, Database.Simple_Uppercase, SUC_Value.String); end if; if SLC_Value /= null then Database.Set (Code, Database.Simple_Lowercase, SLC_Value.String); end if; if STC_Value /= null then Database.Set (Code, Database.Simple_Titlecase, STC_Value.String); end if; if SCF_Value /= null then Database.Set (Code, Database.Simple_Case_Folding, SCF_Value.String); end if; if LC_Value /= null then Database.Set (Code, Database.Full_Lowercase, LC_Value.String); elsif SLC_Value /= null then Database.Set (Code, Database.Full_Lowercase, SLC_Value.String); end if; if TC_Value /= null then Database.Set (Code, Database.Full_Titlecase, TC_Value.String); elsif STC_Value /= null then Database.Set (Code, Database.Full_Titlecase, STC_Value.String); end if; if UC_Value /= null then Database.Set (Code, Database.Full_Uppercase, UC_Value.String); elsif SUC_Value /= null then Database.Set (Code, Database.Full_Uppercase, SUC_Value.String); end if; if CF_Value /= null then Database.Set (Code, Database.Full_Case_Folding, CF_Value.String); elsif SCF_Value /= null then Database.Set (Code, Database.Full_Case_Folding, SCF_Value.String); end if; if NFKC_CF_Value /= null then Database.Set (Code, Database.NFKC_Casefold, NFKC_CF_Value.String); end if; Database.Set_Cased (Code, Cased_Value); Database.Set_Case_Ignorable (Code, CI_Value); -- Compute changes for casing context. Database.Set_Final_Sigma_Enter (Code, Cased_Value and not CI_Value); Database.Set_Final_Sigma_Continue (Code, CI_Value); Database.Set_After_Soft_Dotted_Enter (Code, SD_Value); Database.Set_After_Soft_Dotted_Continue (Code, not (CCC_0_Value or CCC_230_Value)); Database.Set_After_I_Enter (Code, Code = Wide_Wide_Character'Pos ('I')); Database.Set_After_I_Continue (Code, not (CCC_0_Value or CCC_230_Value)); end; end loop; Database.Compress; Database.Print_Statistics; end Build; -------------- -- Database -- -------------- package body Database is type Casing_Context_Change is record Enter_Final_Sigma : Boolean := False; Continue_Final_Sigma : Boolean := False; Enter_After_Soft_Dotted : Boolean := False; Continue_After_Soft_Dotted : Boolean := False; Enter_After_I : Boolean := False; Continue_After_I : Boolean := False; end record with Pack; for Casing_Context_Change'Size use 6; -- This type must be synchronized with type in the package -- VSS.Implementation.UCD_Casing. type Simplified_Mapping_Record is record Offset : Unsigned_15 := 0; Length : Unsigned_5 := 0; Size : Unsigned_6 := 0; Changes : Boolean := False; Reserved_1 : Unsigned_1 := 0; Reserved_2 : Unsigned_3 := 0; Reserved_3 : Unsigned_1 := 0; end record; for Simplified_Mapping_Record'Size use 32; for Simplified_Mapping_Record use record Offset at 0 range 0 .. 14; Reserved_1 at 0 range 15 .. 15; Length at 0 range 16 .. 20; Reserved_2 at 0 range 21 .. 23; Size at 0 range 24 .. 29; Reserved_3 at 0 range 30 .. 30; Changes at 0 range 31 .. 31; end record; -- This declaration must be synchronized with type declaration in the -- generated code. -- -- This record contains additional information that may be derived or -- by copy of core properties when is in interest of casing algorithms. -- This not increase total amount of the data for UCD, but allows to -- have all necessary data in one place, primary to minimize CPU cache -- usage. type Contextual_Mapping_Record is record Offset : Unsigned_15 := 0; Length : Unsigned_2 := 0; Size : Unsigned_3 := 0; Context_Change : Casing_Context_Change; Cased : Boolean := False; Case_Ignorable : Boolean := False; Changes : Boolean := False; Reserved_1 : Unsigned_1 := 0; Reserved_2 : Unsigned_1 := 0; Reserved_3 : Unsigned_1 := 0; end record; for Contextual_Mapping_Record'Size use 32; for Contextual_Mapping_Record use record Offset at 0 range 0 .. 14; Reserved_1 at 0 range 15 .. 15; Length at 0 range 16 .. 17; Context_Change at 0 range 18 .. 23; Size at 0 range 24 .. 26; Reserved_2 at 0 range 27 .. 27; Cased at 0 range 28 .. 28; Case_Ignorable at 0 range 29 .. 29; Reserved_3 at 0 range 30 .. 30; Changes at 0 range 31 .. 31; end record; -- This declaration must be synchronized with type declaration in the -- generated code. -- -- This record contains additional information that may be derived or -- by copy of core properties when is in interest of casing algorithms. -- This not increase total amount of the data for UCD, but allows to -- have all necessary data in one place, primary to minimize CPU cache -- usage. type Mapping_Record (Is_Simplified : Boolean := False) is record case Is_Simplified is when False => Contextual : Contextual_Mapping_Record; when True => Simplified : Simplified_Mapping_Record; end case; end record with Unchecked_Union, Size => 32; overriding function "=" (Left : Mapping_Record; Right : Mapping_Record) return Boolean; type Mapping_Array is array (UCD.Code_Point) of Mapping_Record; type Mapping_Array_Access is access all Mapping_Array; Raw_Mapping : array (Case_Mapping) of Mapping_Array_Access; Max_Length : Natural := 0; Max_UTF_8 : Natural := 0; Total_UTF_8 : Natural := 0; package Compressed_Stage_Table is new Gen_UCD.Generic_Compressed_Stage_Table (Mapping_Record, Mapping_Array); Compressed : array (Case_Mapping) of Compressed_Stage_Table.Compressed_Stage_Table; UTF_8_Data : Gen_UCD.Compressed_UTF_8_Data.Compressed_UTF_8_Data; --------- -- "=" -- --------- overriding function "=" (Left : Mapping_Record; Right : Mapping_Record) return Boolean is function To_Unsigned_32 is new Ada.Unchecked_Conversion (Mapping_Record, Unsigned_32); begin return To_Unsigned_32 (Left) = To_Unsigned_32 (Right); end "="; -------------- -- Compress -- -------------- procedure Compress is begin for J in Case_Mapping'Range loop Compressed (J).Build (Raw_Mapping (J).all); end loop; end Compress; ---------------- -- Initialize -- ---------------- procedure Initialize is begin for M in Case_Mapping'Range loop Raw_Mapping (M) := new Mapping_Array; end loop; end Initialize; -------------------------- -- Mapping_Data_Element -- -------------------------- function Mapping_Data_Element (Offset : Natural) return Unsigned_32 is function To_Unsigned_32 is new Ada.Unchecked_Conversion (Mapping_Record, Unsigned_32); begin return To_Unsigned_32 (Compressed_Stage_Table.Data_Table_Element (Compressed_Stage_Table.Data_Count (Offset))); end Mapping_Data_Element; ----------------------- -- Mapping_Data_Last -- ----------------------- function Mapping_Data_Last return Natural is begin return Natural (Compressed_Stage_Table.Data_Table_Last); end Mapping_Data_Last; --------------------------- -- Mapping_Index_Element -- --------------------------- function Mapping_Index_Element (Mapping : Case_Mapping; Offset : Natural) return Natural is begin return Natural (Compressed (Mapping).Index_Table_Element (Compressed_Stage_Table.Group_Offset (Offset))); end Mapping_Index_Element; ------------------------------ -- Mapping_Index_Group_Size -- ------------------------------ function Mapping_Index_Group_Size (Mapping : Case_Mapping) return Natural is pragma Unreferenced (Mapping); begin return Compressed_Stage_Table.Group_Size; end Mapping_Index_Group_Size; ------------------------ -- Mapping_Index_Last -- ------------------------ function Mapping_Index_Last (Mapping : Case_Mapping) return Natural is begin return Natural (Compressed (Mapping).Index_Table_Last); end Mapping_Index_Last; ---------------------- -- Print_Statistics -- ---------------------- procedure Print_Statistics is begin Put_Line (" max expanded length is" & Natural'Wide_Wide_Image (Max_Length) & " max UTF-8 sequence is" & Natural'Wide_Wide_Image (Max_UTF_8)); Put_Line (" UTF-8 data size is" & Natural'Wide_Wide_Image (Total_UTF_8) & " bytes (compressed size is" & Natural'Wide_Wide_Image (Natural (UTF_8_Data.Last_Index) + 1) & " bytes)"); end Print_Statistics; --------- -- Set -- --------- procedure Set (Character : UCD.Code_Point; Mapping : Case_Mapping; Data : UCD.Code_Point_Vectors.Vector) is Offset : Gen_UCD.UTF_8_Offset; Size : Gen_UCD.UTF_8_Count; Length : Natural; begin UTF_8_Data.Append_Data (Data, Offset, Size, Length); if Mapping in Simple_Case_Mapping then Raw_Mapping (Mapping) (Character).Simplified.Changes := True; Raw_Mapping (Mapping) (Character).Simplified.Offset := Unsigned_15 (Offset); Raw_Mapping (Mapping) (Character).Simplified.Size := Unsigned_6 (Size); Raw_Mapping (Mapping) (Character).Simplified.Length := Unsigned_5 (Length); else Raw_Mapping (Mapping) (Character).Contextual.Changes := True; Raw_Mapping (Mapping) (Character).Contextual.Offset := Unsigned_15 (Offset); Raw_Mapping (Mapping) (Character).Contextual.Size := Unsigned_3 (Size); Raw_Mapping (Mapping) (Character).Contextual.Length := Unsigned_2 (Length); end if; Max_Length := Natural'Max (Max_Length, Length); Max_UTF_8 := Natural'Max (Max_UTF_8, Natural (Size)); Total_UTF_8 := Total_UTF_8 + Natural (Size); end Set; -------------------------- -- Set_After_I_Continue -- -------------------------- procedure Set_After_I_Continue (Character : UCD.Code_Point; To : Boolean) is begin for Mapping in Full_Case_Mapping loop Raw_Mapping (Mapping) (Character).Contextual.Context_Change .Continue_After_I := To; end loop; end Set_After_I_Continue; ----------------------- -- Set_After_I_Enter -- ----------------------- procedure Set_After_I_Enter (Character : UCD.Code_Point; To : Boolean) is begin for Mapping in Full_Case_Mapping loop Raw_Mapping (Mapping) (Character).Contextual.Context_Change .Enter_After_I := To; end loop; end Set_After_I_Enter; ------------------------------------ -- Set_After_Soft_Dotted_Continue -- ------------------------------------ procedure Set_After_Soft_Dotted_Continue (Character : UCD.Code_Point; To : Boolean) is begin for Mapping in Full_Case_Mapping loop Raw_Mapping (Mapping) (Character).Contextual.Context_Change .Continue_After_Soft_Dotted := To; end loop; end Set_After_Soft_Dotted_Continue; --------------------------------- -- Set_After_Soft_Dotted_Enter -- --------------------------------- procedure Set_After_Soft_Dotted_Enter (Character : UCD.Code_Point; To : Boolean) is begin for Mapping in Full_Case_Mapping loop Raw_Mapping (Mapping) (Character).Contextual.Context_Change .Enter_After_Soft_Dotted := To; end loop; end Set_After_Soft_Dotted_Enter; ------------------------ -- Set_Case_Ignorable -- ------------------------ procedure Set_Case_Ignorable (Character : UCD.Code_Point; To : Boolean) is begin for Mapping in Full_Case_Mapping loop Raw_Mapping (Mapping) (Character).Contextual.Case_Ignorable := To; end loop; end Set_Case_Ignorable; --------------- -- Set_Cased -- --------------- procedure Set_Cased (Character : UCD.Code_Point; To : Boolean) is begin for Mapping in Full_Case_Mapping loop Raw_Mapping (Mapping) (Character).Contextual.Cased := To; end loop; end Set_Cased; ------------------------------ -- Set_Final_Sigma_Continue -- ------------------------------ procedure Set_Final_Sigma_Continue (Character : UCD.Code_Point; To : Boolean) is begin for Mapping in Full_Case_Mapping loop Raw_Mapping (Mapping) (Character).Contextual.Context_Change .Continue_Final_Sigma := To; end loop; end Set_Final_Sigma_Continue; --------------------------- -- Set_Final_Sigma_Enter -- --------------------------- procedure Set_Final_Sigma_Enter (Character : UCD.Code_Point; To : Boolean) is begin for Mapping in Full_Case_Mapping loop Raw_Mapping (Mapping) (Character).Contextual.Context_Change .Enter_Final_Sigma := To; end loop; end Set_Final_Sigma_Enter; ------------------------ -- UTF_8_Data_Element -- ------------------------ function UTF_8_Data_Element (Index : Gen_UCD.UTF_8_Offset) return Gen_UCD.UTF_8_Code_Unit is begin return UTF_8_Data.Element (Index); end UTF_8_Data_Element; --------------------------- -- UTF_8_Data_Index_Last -- --------------------------- function UTF_8_Data_Index_Last return Gen_UCD.UTF_8_Offset is begin return UTF_8_Data.Last_Index; end UTF_8_Data_Index_Last; end Database; -------------- -- Generate -- -------------- procedure Generate (File : Ada.Wide_Wide_Text_IO.File_Type) is procedure Generate_Index_Table (Mapping : Database.Case_Mapping; Name : Wide_Wide_String); -------------------------- -- Generate_Index_Table -- -------------------------- procedure Generate_Index_Table (Mapping : Database.Case_Mapping; Name : Wide_Wide_String) is Image : Wide_Wide_String (1 .. 8); begin Put_Line (File, " " & Name & " :"); Put_Line (File, " constant Mapping_Data_Offset_Array :="); for J in 0 .. Database.Mapping_Index_Last (Mapping) loop Put (Image, Database.Mapping_Index_Element (Mapping, J)); if J = 0 then Put (File, " ["); elsif J mod 10 = 0 then Put_Line (File, ","); Put (File, " "); else Put (File, ", "); end if; Put (File, Trim (Image, Both)); end loop; Put_Line (File, "];"); New_Line (File); end Generate_Index_Table; begin Put_Line (" ... casing"); Put_Line (File, "pragma Restrictions (No_Elaboration_Code);"); New_Line (File); Put_Line (File, "with VSS.Implementation.Strings;"); Put_Line (File, "with VSS.Implementation.UCD_Casing;"); Put_Line (File, "with VSS.Implementation.UTF8_Encoding;"); Put_Line (File, "with VSS.Unicode;"); Put_Line (File, "with Interfaces;"); New_Line (File); Put_Line (File, "package VSS.Implementation.UCD_Casing_UTF8 is"); New_Line (File); Put_Line (File, " pragma Preelaborate;"); New_Line (File); -- Generate data types Put_Line (File, " subtype Casing_UTF8_Data_Offset is"); Put_Line (File, " VSS.Unicode.UTF8_Code_Unit_Offset range 0 .." & Positive'Wide_Wide_Image (Positive (Database.UTF_8_Data_Index_Last)) & ";"); New_Line (File); Put_Line (File, " subtype Simplified_Casing_Character_Count is"); Put_Line (File, " VSS.Implementation.Strings.Character_Count range 0 .. 18;"); New_Line (File); Put_Line (File, " subtype Contextual_Casing_Character_Count is"); Put_Line (File, " VSS.Implementation.Strings.Character_Count range 0 .. 3;"); New_Line (File); Put_Line (File, " subtype Simplified_Casing_UTF8_Code_Unit_Count is"); Put_Line (File, " VSS.Unicode.UTF8_Code_Unit_Count range 0 .. 33;"); New_Line (File); Put_Line (File, " subtype Contextual_Casing_UTF8_Code_Unit_Count is"); Put_Line (File, " VSS.Unicode.UTF8_Code_Unit_Count range 0 .. 6;"); New_Line (File); Put_Line (File, " type Simplified_Mapping_Information is record"); Put_Line (File, " Offset : Casing_UTF8_Data_Offset;"); Put_Line (File, " Length : Simplified_Casing_Character_Count;"); Put_Line (File, " Count : Simplified_Casing_UTF8_Code_Unit_Count;"); Put_Line (File, " Changes : Boolean;"); Put_Line (File, " -- Equivalent of Changes_On_ for the given mapping"); Put_Line (File, " end record;"); Put_Line (File, " for Simplified_Mapping_Information'Size use 32;"); Put_Line (File, " for Simplified_Mapping_Information use record"); Put_Line (File, " Offset at 0 range 0 .. 14;"); Put_Line (File, " Length at 0 range 16 .. 20;"); Put_Line (File, " Count at 0 range 24 .. 29;"); Put_Line (File, " Changes at 0 range 31 .. 31;"); Put_Line (File, " end record;"); New_Line (File); Put_Line (File, " type Contextual_Mapping_Information is record"); Put_Line (File, " Offset : Casing_UTF8_Data_Offset;"); Put_Line (File, " Length : Contextual_Casing_Character_Count;"); Put_Line (File, " Count : Contextual_Casing_UTF8_Code_Unit_Count;"); Put_Line (File, " Context_Change :" & " VSS.Implementation.UCD_Casing.Casing_Context_Change;"); Put_Line (File, " Cased : Boolean;"); Put_Line (File, " Case_Ignorable : Boolean;"); Put_Line (File, " Changes : Boolean;"); Put_Line (File, " -- Equivalent of Changes_On_ for the given mapping"); Put_Line (File, " end record;"); Put_Line (File, " for Contextual_Mapping_Information'Size use 32;"); Put_Line (File, " for Contextual_Mapping_Information use record"); Put_Line (File, " Offset at 0 range 0 .. 14;"); Put_Line (File, " Length at 0 range 16 .. 17;"); Put_Line (File, " Context_Change at 0 range 18 .. 23;"); Put_Line (File, " Count at 0 range 24 .. 26;"); Put_Line (File, " Cased at 0 range 28 .. 28;"); Put_Line (File, " Case_Ignorable at 0 range 29 .. 29;"); Put_Line (File, " Changes at 0 range 31 .. 31;"); Put_Line (File, " end record;"); New_Line (File); Put_Line (File, " Mapping_Group_Size : constant :=" & Integer'Wide_Wide_Image (Database.Mapping_Index_Group_Size (Database.Simple_Lowercase)) & ";"); New_Line (File); Put_Line (File, " type Mapping_Group is range 0 .." & Integer'Wide_Wide_Image (Database.Mapping_Index_Last (Database.Simple_Lowercase)) & ";"); New_Line (File); Put_Line (File, " type Mapping_Data_Offset is range 0 .." & Integer'Wide_Wide_Image (Database.Mapping_Data_Last) & ";"); New_Line (File); Put_Line (File, " type Mapping_Data_Offset_Array is"); Put_Line (File, " array (Mapping_Group) of Mapping_Data_Offset;"); New_Line (File); -- Generate case mappings indices. Generate_Index_Table (Database.Simple_Lowercase, "Simple_Lowercase_Index"); Generate_Index_Table (Database.Simple_Titlecase, "Simple_Titlecase_Index"); Generate_Index_Table (Database.Simple_Uppercase, "Simple_Uppercase_Index"); Generate_Index_Table (Database.Simple_Case_Folding, "Simple_Case_Folding_Index"); Generate_Index_Table (Database.Full_Lowercase, "Full_Lowercase_Index"); Generate_Index_Table (Database.Full_Titlecase, "Full_Titlecase_Index"); Generate_Index_Table (Database.Full_Uppercase, "Full_Uppercase_Index"); Generate_Index_Table (Database.Full_Case_Folding, "Full_Case_Folding_Index"); Generate_Index_Table (Database.NFKC_Casefold, "NFKC_Casefold_Index"); -- Generate mapping data table. declare package Mapping_Data_IO is new Ada.Wide_Wide_Text_IO.Modular_IO (Unsigned_32); use Mapping_Data_IO; Image : Wide_Wide_String (1 .. 12); begin Put_Line (File, " Mapping_Data_Table_Raw :"); Put_Line (File, " constant array (Mapping_Data_Offset)"); Put_Line (File, " of Interfaces.Unsigned_32 :="); for J in 0 .. Database.Mapping_Data_Last loop Put (Image, Database.Mapping_Data_Element (J), 16); if J = 0 then Put (File, " ["); elsif J mod 4 = 0 then Put_Line (File, ","); Put (File, " "); else Put (File, ", "); end if; Put (File, Trim (Image, Both)); end loop; Put_Line (File, "];"); New_Line (File); Put_Line (File, " Simplified_Mapping_Data_Table :"); Put_Line (File, " constant array (Mapping_Data_Offset)" & " of Simplified_Mapping_Information"); Put_Line (File, " with Import,"); Put_Line (File, " Convention => Ada,"); Put_Line (File, " Address => Mapping_Data_Table_Raw'Address;"); New_Line (File); Put_Line (File, " Contextual_Mapping_Data_Table :"); Put_Line (File, " constant array (Mapping_Data_Offset)" & " of Contextual_Mapping_Information"); Put_Line (File, " with Import,"); Put_Line (File, " Convention => Ada,"); Put_Line (File, " Address => Mapping_Data_Table_Raw'Address;"); New_Line (File); end; -- Generate UTF-8 encoded data. declare Image : Wide_Wide_String (1 .. 10); begin Put_Line (File, " UTF8_Data_Table :"); Put_Line (File, " constant" & " VSS.Implementation.UTF8_Encoding.UTF8_Code_Unit_Array"); Put_Line (File, " (Casing_UTF8_Data_Offset) :="); for J in 0 .. Database.UTF_8_Data_Index_Last loop Put (Image, Integer (Database.UTF_8_Data_Element (J)), 16); if J = 0 then Put (File, " ["); elsif J mod 8 = 0 then Put_Line (File, ","); Put (File, " "); else Put (File, ", "); end if; Put (File, Trim (Image, Both)); end loop; Put_Line (File, "];"); New_Line (File); end; Put_Line (File, "end VSS.Implementation.UCD_Casing_UTF8;"); end Generate; end Gen_UCD.Casing;