home *** CD-ROM | disk | FTP | other *** search
/ Hacker / Hacker.iso / HACKER / DECOMP / DECAF / cp-utf8.adb < prev    next >
Encoding:
Text File  |  1996-09-19  |  10.7 KB  |  292 lines

  1. --
  2. -- Copyright (C) 1996 Ada Resource Association (ARA), Columbus, Ohio.
  3. -- Author: Gilles Demailly
  4. --
  5. --
  6. -- Permission to use, copy, modify, and distribute this software and its
  7. -- documentation for any purpose and without fee is hereby granted,
  8. -- provided that the above copyright and authorship notice appear in all
  9. -- copies and that both that copyright notice and this permission notice
  10. -- appear in supporting documentation.
  11. -- 
  12. -- The ARA makes no representations about the suitability of this software
  13. -- for any purpose.  It is provided "as is" without express
  14. -- or implied warranty.
  15. -- 
  16.  
  17. with Ada.Text_Io;
  18. with Ada.Unchecked_Conversion;
  19. with Ada.Characters.Handling;
  20.  
  21. package body CP.Utf8 is
  22.  
  23.    use Byte_Utilities;
  24.    use Ada.Strings.Wide_Unbounded;
  25.  
  26.    -- Limit value for a character represented by a single byte
  27.    C_One_Byte : constant Unsigned_8 := 2#10000000#;
  28.  
  29.    -- Limit value for a character represented by two bytes or three bytes
  30.    -- (under : two bytes, over : three bytes)
  31.    C_Two_Bytes : constant Unsigned_8 := 2#11100000#;
  32.    
  33.    E_Bad_String : exception;
  34.  
  35.    -- Utf8 characters are represented in decaf as Wide_Characters
  36.    -- instanciation of the conversion between Unsigned_16 and Wide_Character
  37.    function To_Wide is new Ada.Unchecked_Conversion
  38.                               (Unsigned_16, Wide_Character);
  39.  
  40.  
  41.  
  42.    procedure Decode_String (Some_Info : access Utf8) is
  43.       Index  : Unsigned_32 := 1;
  44.       Answer : Wide_String (1..Natural(Some_Info.Length));
  45.       Length : Natural := 0;
  46.    begin
  47.       while Index <= Unsigned_32 (Some_Info.Length) loop
  48.          Length := Length + 1;
  49.          if Some_Info.bytes (Index) < C_One_Byte then
  50.             -- character represented by a single byte
  51.             -- conversion from a byte to a character 
  52.             Answer (Length) := To_Wide (Unsigned_16 (Some_Info.bytes (Index)));
  53.             Index := Index + 1;
  54.          elsif Some_Info.bytes (Index) < C_Two_Bytes then
  55.             -- character represented by two bytes
  56.             Answer (Length) := '?';
  57.             Ada.Text_Io.Put_Line
  58.                ("Warning : this version does not handle characters stored on multiple bytes.");
  59.             Ada.Text_Io.Put_Line
  60.                ("          no test has been conducted with multiple bytes characters.");
  61.             Ada.Text_Io.Put_Line
  62.                ("          proceeding ...");
  63.             Index := Index + 2;
  64.          else
  65.             -- character represented by three bytes
  66.             Answer (Length) := '?';
  67.             Ada.Text_Io.Put_Line
  68.                ("Warning : this version does not handle characters stored on multiple bytes.");
  69.             Ada.Text_Io.Put_Line
  70.                ("          no test has been conducted with multiple bytes characters.");
  71.             Ada.Text_Io.Put_Line
  72.                ("          proceeding ...");
  73.             Index := Index + 3;
  74.          end if;
  75.  
  76.       end loop;
  77.  
  78.       -- stores the String
  79.       Some_Info.Contents := To_Unbounded_Wide_String (Answer (1..Length));
  80.    end Decode_String;
  81.    
  82.    procedure Decode (From_File : Byte_Utilities.File_Type;
  83.                      Some_Info : access Utf8) is
  84.    begin
  85.       Some_Info.Tag := C_Class_Tag;
  86.  
  87.       -- Reads the String length
  88.       Read (From_File, Some_Info.Length);
  89.  
  90.       -- byte array allocation
  91.       Some_Info.bytes := new Bytes (1..Unsigned_32(Some_Info.Length));
  92.  
  93.       -- Reads the bytes
  94.       for I in 1..Unsigned_32(Some_Info.Length) loop
  95.          Read (From_File, Some_Info.bytes (I));
  96.       end loop;
  97.  
  98.       -- Decode the string from the bytes
  99.       Decode_String (Some_Info);
  100.    end Decode;
  101.  
  102.    procedure Display (Some_Info : access Utf8;
  103.                       Context   : in Acc_CP_Infos) is
  104.    begin
  105.       -- Displays the String
  106.       Ada.Text_Io.Put 
  107.          (Ada.Characters.Handling.To_String (
  108.           To_Wide_String (Some_Info.Contents)));
  109.    end Display;
  110.  
  111.    function As_String
  112.                (Some_Info : access Utf8) return Wide_String is
  113.    begin
  114.       return To_Wide_String (Some_Info.Contents);
  115.    end As_String;
  116.    
  117.    function Print_String
  118.                (Some_Info : access Utf8;
  119.                 Context   : in Acc_CP_Infos) return String is
  120.    begin
  121.       return Ada.Characters.Handling.To_String
  122.                 (To_Wide_String (Some_Info.Contents));
  123.    end Print_String;
  124.    
  125.    function Java_Decoded_String
  126.                (Some_Info : access Utf8;
  127.                 Context   : Acc_CP_Infos;
  128.                 Purpose   : Decoding_Purpose) return String is 
  129.       From         : constant String := Print_String (Some_Info, Context);
  130.       Answer       : String (1..From'Length + 1024);
  131.       Index        : Natural := 0;
  132.       Answer_Index : Natural := 0;
  133.       Char         : Character;
  134.       Continue     : Boolean;
  135.       Is_Array     : Boolean := False;
  136.       Array_Size   : String (1..50);
  137.       Array_Index  : Natural := 0;
  138.       Is_Argument  : Boolean := False;
  139.       
  140.       procedure Test_Array is
  141.       begin
  142.          if char /= '[' and then Is_Array then
  143.             if Array_Index = 0 then
  144.                Answer (Answer_Index + 1..Answer_Index + 3) := " []";
  145.                Answer_Index := Answer_Index + 3;
  146.             else
  147.                Answer (Answer_Index + 1..Answer_Index + 2) := " [";
  148.                Answer_Index := Answer_Index + 2;
  149.                Answer (Answer_Index + 1..Answer_Index + Array_Index) := 
  150.                  Array_Size (1..Answer_Index);
  151.                Answer_Index := Answer_Index + Array_Index;
  152.                Answer (Answer_Index + 1..Answer_Index + 1) := "]";
  153.                Answer_Index := Answer_Index + 1;
  154.             end if;
  155.             Is_Array     := False;
  156.          end if;
  157.       end Test_Array;
  158.       
  159.       procedure Test_Argument is
  160.       begin
  161.          if Char /= '(' and then
  162.             Char /= '[' and then
  163.             Is_Argument and then
  164.             From (From'First + Index + 1) /= ')' then
  165.             Answer (Answer_Index + 1..Answer_Index + 2) := ", ";
  166.             Answer_Index := Answer_Index + 2;
  167.          end if;
  168.       end Test_Argument;
  169.       
  170.       procedure Decode_Signature is
  171.       begin
  172.          while Index < From'Length loop
  173.             Char := From (From'First + Index);
  174.             case Char is
  175.                when '[' =>
  176.                   -- this is an array
  177.                   Is_Array    := True;
  178.                   Array_Index := 0;
  179.                   Char        := From (From'First + Index + 1);
  180.                   while Ada.Characters.Handling.Is_Digit (Char) loop
  181.                      Array_Index := Array_Index + 1;
  182.                      Array_Size (Array_Index) := Char;
  183.                      Index := Index + 1;
  184.                      Char  := From (From'First + Index + 1);
  185.                   end loop;
  186.                   Char := '[';
  187.                when 'B' =>
  188.                   -- type Byte
  189.                   Answer (Answer_Index + 1..Answer_Index + 4) := "byte";
  190.                   Answer_Index := Answer_Index + 4;
  191.                when 'C' =>
  192.                   -- type Char
  193.                   Answer (Answer_Index + 1..Answer_Index + 4) := "char";
  194.                   Answer_Index := Answer_Index + 4;
  195.                when 'D' =>
  196.                   -- type Double Float
  197.                   Answer (Answer_Index + 1..Answer_Index + 6) := "double";
  198.                   Answer_Index := Answer_Index + 6;
  199.                when 'F' =>
  200.                   -- type Single Float
  201.                   Answer (Answer_Index + 1..Answer_Index + 5) := "float";
  202.                   Answer_Index := Answer_Index + 5;
  203.                when 'I' =>
  204.                   -- type Integer
  205.                   Answer (Answer_Index + 1..Answer_Index + 3) := "int";
  206.                   Answer_Index := Answer_Index + 3;
  207.                when 'J' =>
  208.                   -- type Long Integer
  209.                   Answer (Answer_Index + 1..Answer_Index + 4) := "long";
  210.                   Answer_Index := Answer_Index + 4;
  211.                when 'L' =>
  212.                   -- this is an object of a given class
  213.                   Index    := Index + 1;
  214.                   Continue := True;
  215.                   while Continue loop
  216.                      Char := From (From'First + Index);
  217.                      if Char = ';' then
  218.                         -- end of name
  219.                         Continue := False;
  220.                      else
  221.                         if Char = '/' then
  222.                            Answer (Answer_Index + 1) := '.';
  223.                         else
  224.                            Answer (Answer_Index + 1) := Char;
  225.                         end if;
  226.                         Answer_Index := Answer_Index + 1;
  227.                         Index        := Index + 1;
  228.                         Continue     := Index < From'Length;
  229.                      end if;
  230.                   end loop;
  231.                when 'S' =>
  232.                   -- type Signed Short
  233.                   Answer (Answer_Index + 1..Answer_Index + 5) := "short";
  234.                   Answer_Index := Answer_Index + 5;
  235.                when 'V' =>
  236.                   -- type Void
  237.                   Answer (Answer_Index + 1..Answer_Index + 4) := "void";
  238.                   Answer_Index := Answer_Index + 4;
  239.                when 'Z' =>
  240.                   -- type Boolean
  241.                   Answer (Answer_Index + 1..Answer_Index + 7) := "boolean";
  242.                   Answer_Index := Answer_Index + 7;
  243.                when '(' =>
  244.                   -- this is an argument list beginning
  245.                   if From (From'First + Index + 1) = ')' then
  246.                      Answer (Answer_Index + 1..Answer_Index + 2) := "()";
  247.                      Answer_Index := Answer_Index + 2;
  248.                      Index := Index + 1;
  249.                   else
  250.                      Answer (Answer_Index + 1) := '(';
  251.                      Answer_Index := Answer_Index + 1;
  252.                      Is_Argument := True;
  253.                   end if;
  254.                when ')' =>
  255.                   -- this is an argument list end
  256.                   Answer (Answer_Index + 1) := ')';
  257.                   Answer_Index := Answer_Index + 1;
  258.                   Is_Argument := False;
  259.                when others =>
  260.                   raise E_Bad_String;
  261.             end case;
  262.             Test_Array;
  263.             Test_Argument;
  264.             Index := Index + 1;
  265.          end loop;
  266.       end Decode_Signature;
  267.       
  268.       procedure Decode_Name is
  269.       begin
  270.          while Index < From'Length loop
  271.             Char := From (From'First + Index);
  272.             Answer_Index := Answer_Index + 1;
  273.             if Char = '/' then
  274.                Answer (Answer_Index) := '.';
  275.             else
  276.                Answer (Answer_Index) := Char;
  277.             end if;
  278.             Index := Index + 1;
  279.          end loop;
  280.       end Decode_Name;
  281.       
  282.    begin
  283.       case Purpose is 
  284.          when Class_Name          => Decode_Name;
  285.          when Variable_Signature  => Decode_Signature;
  286.          when Method_Signature    => Decode_Signature;
  287.       end case;
  288.       return Answer (1..Answer_Index);
  289.    end Java_Decoded_String;
  290.  
  291. end CP.Utf8;
  292.