1-----------------------------------------------------------------------
2--  util-encoders -- Encode/Decode streams and strings from one format to another
3--  Copyright (C) 2009, 2010, 2011, 2012 Stephane Carrez
4--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
5--
6--  Licensed under the Apache License, Version 2.0 (the "License");
7--  you may not use this file except in compliance with the License.
8--  You may obtain a copy of the License at
9--
10--      http://www.apache.org/licenses/LICENSE-2.0
11--
12--  Unless required by applicable law or agreed to in writing, software
13--  distributed under the License is distributed on an "AS IS" BASIS,
14--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15--  See the License for the specific language governing permissions and
16--  limitations under the License.
17-----------------------------------------------------------------------
18with Ada.Streams;
19with Ada.Finalization;
20with Ada.Strings.Unbounded;
21with Interfaces;
22
23--  The <b>Util.Encoders</b> package defines the <b>Encoder</b> object
24--  which represents a mechanism to transform a stream from one format into
25--  another format.
26package Util.Encoders is
27
28   pragma Preelaborate;
29
30   Not_Supported  : exception;
31   Encoding_Error : exception;
32
33   --  Encoder/decoder for Base64 (RFC 4648)
34   BASE_64     : constant String := "base64";
35
36   --  Encoder/decoder for Base64 (RFC 4648) using the URL alphabet
37   --  (+ and / are replaced by - and _)
38   BASE_64_URL : constant String := "base64url";
39
40   --  Encoder/decoder for Base16 (RFC 4648)
41   BASE_16     : constant String := "base16";
42   HEX         : constant String := "hex";
43
44   --  Encoder for SHA1 (RFC 3174)
45   HASH_SHA1   : constant String := "sha1";
46
47   --  ------------------------------
48   --  Encoder context object
49   --  ------------------------------
50   --  The <b>Encoder</b> provides operations to encode and decode
51   --  strings or stream of data from one format to another.
52   --  The <b>Encoded</b> contains two <b>Transformer</b>
53   --  which either <i>encodes</i> or <i>decodes</i> the stream.
54   type Encoder is tagged limited private;
55
56   --  Encodes the input string <b>Data</b> using the transformation
57   --  rules provided by the <b>E</b> encoder.
58   --
59   --  Returns the encoded string.
60   --
61   --  Raises the <b>Encoding_Error</b> exception if the source string
62   --  cannot be encoded.
63   --  Raises the <b>Not_Supported</b> exception if the encoding is not
64   --  supported.
65   function Encode (E    : in Encoder;
66                    Data : in String) return String;
67
68   --  Decodes the input string <b>Data</b> using the transformation
69   --  rules provided by the <b>E</b> encoder.
70   --
71   --  Returns the encoded string.
72   --
73   --  Raises the <b>Encoding_Error</b> exception if the source string
74   --  cannot be decoded.
75   --  Raises the <b>Not_Supported</b> exception if the decoding is not
76   --  supported.
77   function Decode (E    : in Encoder;
78                    Data : in String) return String;
79
80   --  Create the encoder object for the specified encoding format.
81   function Create (Name : String) return Encoder;
82
83   --  ------------------------------
84   --  Stream Transformation interface
85   --  ------------------------------
86   --  The <b>Transformer</b> interface defines the operation to transform
87   --  a stream from one data format to another.
88   type Transformer is limited interface;
89   type Transformer_Access is access all Transformer'Class;
90
91   --  Transform the input stream represented by <b>Data</b> into
92   --  the output stream <b>Into</b>.  The transformation made by
93   --  the object can be of any nature (Hex encoding, Base64 encoding,
94   --  Hex decoding, Base64 decoding, ...).
95   --
96   --  If the transformer does not have enough room to write the result,
97   --  it must return in <b>Encoded</b> the index of the last encoded
98   --  position in the <b>Data</b> stream.
99   --
100   --  The transformer returns in <b>Last</b> the last valid position
101   --  in the output stream <b>Into</b>.
102   --
103   --  The <b>Encoding_Error</b> exception is raised if the input
104   --  stream cannot be transformed.
105   procedure Transform (E       : in Transformer;
106                        Data    : in Ada.Streams.Stream_Element_Array;
107                        Into    : out Ada.Streams.Stream_Element_Array;
108                        Last    : out Ada.Streams.Stream_Element_Offset;
109                        Encoded : out Ada.Streams.Stream_Element_Offset) is abstract;
110
111   procedure Transform (E    : in Transformer;
112                        Data : in String;
113                        Result : out Ada.Strings.Unbounded.Unbounded_String) is null;
114
115   --  Transform the input string <b>Data</b> using the transformation
116   --  rules provided by the <b>E</b> transformer.
117   --
118   --  Returns the transformed string.
119   --
120   --  Raises the <b>Encoding_Error</b> exception if the source string
121   --  cannot be transformed
122   function Transform (E    : in Transformer'Class;
123                       Data : in String) return String;
124
125   --  Transform the input string <b>Data</b> using the transformation
126   --  rules provided by the <b>E</b> transformer.
127   --
128   --  Returns the transformed string.
129   --
130   --  Raises the <b>Encoding_Error</b> exception if the source string
131   --  cannot be transformed
132   function Transform (E    : in Transformer'Class;
133                       Data : in Ada.Streams.Stream_Element_Array) return String;
134
135   --  Encode the value represented by <tt>Val</tt> in the stream array <tt>Into</tt> starting
136   --  at position <tt>Pos</tt> in that array.  The value is encoded using LEB128 format, 7-bits
137   --  at a time until all non zero bits are written.  The <tt>Last</tt> parameter is updated
138   --  to indicate the position of the last valid byte written in <tt>Into</tt>.
139   procedure Encode_LEB128 (Into  : in out Ada.Streams.Stream_Element_Array;
140                            Pos   : in Ada.Streams.Stream_Element_Offset;
141                            Val   : in Interfaces.Unsigned_64;
142                            Last  : out Ada.Streams.Stream_Element_Offset);
143
144   --  Decode from the byte array <tt>From</tt> the value represented as LEB128 format starting
145   --  at position <tt>Pos</tt> in that array.  After decoding, the <tt>Last</tt> index is updated
146   --  to indicate the last position in the byte array.
147   procedure Decode_LEB128 (From  : in Ada.Streams.Stream_Element_Array;
148                            Pos   : in Ada.Streams.Stream_Element_Offset;
149                            Val   : out Interfaces.Unsigned_64;
150                            Last  : out Ada.Streams.Stream_Element_Offset);
151
152private
153
154   type Encoder is new Ada.Finalization.Limited_Controlled with record
155      Encode : Transformer_Access := null;
156      Decode : Transformer_Access := null;
157   end record;
158
159   --  Delete the transformers
160   overriding
161   procedure Finalize (E : in out Encoder);
162
163end Util.Encoders;
164