Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | smaz_64: new instance of generic smaz, outputs directly base-64 symbols |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
091a96ec6c6490323653b531e740e7d7 |
User & Date: | nat 2016-12-19 20:18:19 |
Context
2016-12-20
| ||
21:55 | tools/smaz: add support for base-64 variant check-in: 9de1423410 user: nat tags: trunk | |
2016-12-19
| ||
20:18 | smaz_64: new instance of generic smaz, outputs directly base-64 symbols check-in: 091a96ec6c user: nat tags: trunk | |
2016-12-18
| ||
21:16 | smaz_implementations-base_64_tools: new package for paddingless base-64 check-in: fd2ccb00b9 user: nat tags: trunk | |
Changes
Added src/natools-smaz_64.ads.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | ------------------------------------------------------------------------------ -- Copyright (c) 2016, Natacha Porté -- -- -- -- Permission to use, copy, modify, and distribute this software for any -- -- purpose with or without fee is hereby granted, provided that the above -- -- copyright notice and this permission notice appear in all copies. -- -- -- -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -- -- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -- -- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -- -- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- Natools.Smaz_Implementations.Base_64 provides the subprograms needed to -- -- instantiate Natools.Smaz_Generic into a variant of the Smaz compression -- -- algorithm that output directly base-64 printable symbols, but with a -- -- dictionary containing at most 61 elements. -- -- See Natools.Smaz_Implementations.Base_64 comments for the implementation -- -- details. -- ------------------------------------------------------------------------------ with Natools.Smaz_Generic; with Natools.Smaz_Implementations.Base_64; with Natools.Smaz_Implementations.Base_64_Tools; package Natools.Smaz_64 is new Natools.Smaz_Generic (Dictionary_Code => Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit, Read_Code => Natools.Smaz_Implementations.Base_64.Read_Code, Read_Verbatim => Natools.Smaz_Implementations.Base_64.Read_Verbatim, Skip_Verbatim => Natools.Smaz_Implementations.Base_64.Skip_Verbatim, Verbatim_Size => Natools.Smaz_Implementations.Base_64.Verbatim_Size, Write_Code => Natools.Smaz_Implementations.Base_64.Write_Code, Write_Verbatim => Natools.Smaz_Implementations.Base_64.Write_Verbatim); pragma Pure (Natools.Smaz_64); |
Added src/natools-smaz_implementations-base_64.adb.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | ------------------------------------------------------------------------------ -- Copyright (c) 2016, Natacha Porté -- -- -- -- Permission to use, copy, modify, and distribute this software for any -- -- purpose with or without fee is hereby granted, provided that the above -- -- copyright notice and this permission notice appear in all copies. -- -- -- -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -- -- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -- -- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -- -- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- ------------------------------------------------------------------------------ package body Natools.Smaz_Implementations.Base_64 is package Tools renames Natools.Smaz_Implementations.Base_64_Tools; use type Ada.Streams.Stream_Element_Offset; use type Tools.Base_64_Digit; ---------------------- -- Public Interface -- ---------------------- procedure Read_Code (Input : in Ada.Streams.Stream_Element_Array; Offset : in out Ada.Streams.Stream_Element_Offset; Code : out Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit; Verbatim_Length : out Natural; Last_Code : in Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit; Variable_Length_Verbatim : in Boolean) is Ignored : String (1 .. 2); Offset_Backup : Ada.Streams.Stream_Element_Offset; begin Tools.Next_Digit (Input, Offset, Code); if Code <= Last_Code then Verbatim_Length := 0; elsif Variable_Length_Verbatim then Verbatim_Length := 64 - Natural (Code); Code := 0; elsif Code = 63 then Tools.Next_Digit (Input, Offset, Code); Verbatim_Length := Natural (Code) * 3 + 3; Code := 0; elsif Code = 62 then Offset_Backup := Offset; Tools.Decode_Single (Input, Offset, Ignored (1), Code); Verbatim_Length := Natural (Code) * 3 + 1; Offset := Offset_Backup; Code := 0; else Offset_Backup := Offset; Verbatim_Length := (Natural (Code) - 61) * (Natural (Tools.Single_Byte_Padding'Last) + 1); Tools.Decode_Double (Input, Offset, Ignored, Code); Verbatim_Length := (Verbatim_Length + Natural (Code)) * 3 + 2; Offset := Offset_Backup; Code := 0; end if; end Read_Code; procedure Read_Verbatim (Input : in Ada.Streams.Stream_Element_Array; Offset : in out Ada.Streams.Stream_Element_Offset; Output : out String) is Ignored : Tools.Base_64_Digit; Output_Index : Natural := Output'First - 1; begin if Output'Length mod 3 = 1 then Tools.Decode_Single (Input, Offset, Output (Output_Index + 1), Ignored); Output_Index := Output_Index + 1; elsif Output'Length mod 3 = 2 then Tools.Decode_Double (Input, Offset, Output (Output_Index + 1 .. Output_Index + 2), Ignored); Output_Index := Output_Index + 2; end if; if Output_Index < Output'Last then Tools.Decode (Input, Offset, Output (Output_Index + 1 .. Output'Last)); end if; end Read_Verbatim; procedure Skip_Verbatim (Input : in Ada.Streams.Stream_Element_Array; Offset : in out Ada.Streams.Stream_Element_Offset; Verbatim_Length : in Positive) is Code : Tools.Base_64_Digit; begin for I in 1 .. Tools.Image_Length (Verbatim_Length) loop Tools.Next_Digit (Input, Offset, Code); end loop; end Skip_Verbatim; function Verbatim_Size (Input_Length : in Positive; Last_Code : in Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit; Variable_Length_Verbatim : in Boolean) return Ada.Streams.Stream_Element_Count is begin if Variable_Length_Verbatim then declare Largest_Run : constant Positive := 63 - Natural (Last_Code); Run_Count : constant Positive := (Input_Length + Largest_Run - 1) / Largest_Run; Last_Run_Size : constant Positive := Input_Length - (Run_Count - 1) * Largest_Run; begin return Ada.Streams.Stream_Element_Count (Run_Count - 1) * (Tools.Image_Length (Largest_Run) + 1) + Tools.Image_Length (Last_Run_Size) + 1; end; elsif Input_Length mod 3 = 0 then declare Largest_Run : constant Positive := 64 * 3; Run_Count : constant Positive := (Input_Length + Largest_Run - 1) / Largest_Run; Last_Run_Size : constant Positive := Input_Length - (Run_Count - 1) * Largest_Run; begin return Ada.Streams.Stream_Element_Count (Run_Count - 1) * (Tools.Image_Length (Largest_Run) + 2) + Tools.Image_Length (Last_Run_Size) + 2; end; elsif Input_Length mod 3 = 1 then declare Largest_Final_Run : constant Positive := 15 * 3 + 1; Largest_Prefix_Run : constant Positive := 64 * 3; Prefix_Run_Count : constant Natural := (Input_Length + Largest_Prefix_Run - Largest_Final_Run) / Largest_Prefix_Run; Last_Run_Size : constant Positive := Input_Length - Prefix_Run_Count * Largest_Prefix_Run; begin return Ada.Streams.Stream_Element_Count (Prefix_Run_Count) * (Tools.Image_Length (Largest_Prefix_Run) + 2) + Tools.Image_Length (Last_Run_Size) + 1; end; elsif Input_Length mod 3 = 2 then declare Largest_Final_Run : constant Positive := ((62 - Natural (Last_Code)) * 4 - 1) * 3 + 2; Largest_Prefix_Run : constant Positive := 64 * 3; Prefix_Run_Count : constant Natural := (Input_Length + Largest_Prefix_Run - Largest_Final_Run) / Largest_Prefix_Run; Last_Run_Size : constant Positive := Input_Length - Prefix_Run_Count * Largest_Prefix_Run; begin return Ada.Streams.Stream_Element_Count (Prefix_Run_Count) * (Tools.Image_Length (Largest_Prefix_Run) + 2) + Tools.Image_Length (Last_Run_Size) + 1; end; else raise Program_Error with "Condition unreachable"; end if; end Verbatim_Size; procedure Write_Code (Output : in out Ada.Streams.Stream_Element_Array; Offset : in out Ada.Streams.Stream_Element_Offset; Code : in Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit) is begin Output (Offset) := Tools.Image (Code); Offset := Offset + 1; end Write_Code; procedure Write_Verbatim (Output : in out Ada.Streams.Stream_Element_Array; Offset : in out Ada.Streams.Stream_Element_Offset; Input : in String; Last_Code : in Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit; Variable_Length_Verbatim : in Boolean) is Index : Positive := Input'First; begin if Variable_Length_Verbatim then declare Largest_Run : constant Positive := 63 - Natural (Last_Code); Length, Last : Positive; begin while Index in Input'Range loop Length := Positive'Min (Largest_Run, Input'Last + 1 - Index); Last := Index + Length - 1; Output (Offset) := Tools.Image (63 - Tools.Base_64_Digit (Length - 1)); Offset := Offset + 1; Tools.Encode (Input (Index .. Last), Output, Offset); Index := Last + 1; end loop; end; else if Input'Length mod 3 = 1 then declare Extra_Blocks : constant Natural := Natural'Min (15, Input'Length / 3); begin Output (Offset) := Tools.Image (62); Offset := Offset + 1; Tools.Encode_Single (Input (Index), Tools.Single_Byte_Padding (Extra_Blocks), Output, Offset); Index := Index + 1; if Extra_Blocks > 0 then Tools.Encode (Input (Index .. Index + Extra_Blocks * 3 - 1), Output, Offset); Index := Index + Extra_Blocks * 3; end if; end; elsif Input'Length mod 3 = 2 then declare Extra_Blocks : constant Natural := Natural'Min (Input'Length / 3, (62 - Natural (Last_Code)) * 4 - 1); begin Output (Offset) := Tools.Image (61 - Tools.Base_64_Digit (Extra_Blocks / 4)); Offset := Offset + 1; Tools.Encode_Double (Input (Index .. Index + 1), Tools.Double_Byte_Padding (Extra_Blocks mod 4), Output, Offset); Index := Index + 1; if Extra_Blocks > 0 then Tools.Encode (Input (Index .. Index + Extra_Blocks * 3 - 1), Output, Offset); Index := Index + Extra_Blocks * 3; end if; end; end if; pragma Assert ((Input'Last + 1 - Index) mod 3 = 0); while Index <= Input'Last loop declare Block_Count : constant Natural := Natural'Min (64, (Input'Last + 1 - Index) / 3); begin Output (Offset) := Tools.Image (63); Output (Offset + 1) := Tools.Image (Tools.Base_64_Digit (Block_Count - 1)); Offset := Offset + 2; Tools.Encode (Input (Index .. Index + Block_Count * 3 - 1), Output, Offset); Index := Index + Block_Count * 3; end; end loop; end if; end Write_Verbatim; end Natools.Smaz_Implementations.Base_64; |
Added src/natools-smaz_implementations-base_64.ads.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | ------------------------------------------------------------------------------ -- Copyright (c) 2016, Natacha Porté -- -- -- -- Permission to use, copy, modify, and distribute this software for any -- -- purpose with or without fee is hereby granted, provided that the above -- -- copyright notice and this permission notice appear in all copies. -- -- -- -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -- -- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -- -- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -- -- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- Natools.Smaz_Implementations.Base_64 provides the subprograms needed to -- -- instantiate Natools.Smaz_Generic into a variant of the Smaz compression -- -- algorithm that output directly base-64 printable symbols, but with a -- -- dictionary containing at most 61 elements. -- -- -- -- Similarly to original Smaz, low-numbered base-64 digit are indices in -- -- the static dictionary, while high-numbered ones are verbatim headers. -- -- The verbatim headers all indicate a number of bytes in the decoded -- -- stream, and it is encoded without padding characters in the output (e.g. -- -- a two-byte verbatim sequence would be encoded as only three base-64 -- -- symbols). -- -- -- -- When Variable_Length_Verbatim is True, the same scheme as original Smaz -- -- is used: 62 means one verbatim byte (encoded in two base-64 digits), 61 -- -- means two verbatim bytes, and so on, while 63 is followed by the number -- -- of bytes on top of the hardcoded ones. For example, with a 60-entry -- -- dictionary, 59 means the last dictionary entry, and 60 means 3-byte -- -- verbatim string, and 63, 0 means 4-byte verbatim string. -- -- -- -- When Variable_Length_Verbatim is False, another variable-length scheme -- -- is used, where the number of extra blocks is stored in the padding bits. -- -- * 111111 nnnnnn ... means (n+1) 3-byte blocks of verbatim data, -- -- * 111110 AAAAAA AAnnnn ... means n 3-byte blocks and 1 byte (A), -- -- * 111101 AAAAAA AABBBB BBBBnn ... means n 3-byte blocks and 2 bytes -- -- If the dictionary is smaller, the extra codes are used for further 3n+2 -- -- blocks. For example, 60 would then mean 3(n+4)+2 bytes of verbatim data. -- ------------------------------------------------------------------------------ with Ada.Streams; with Natools.Smaz_Implementations.Base_64_Tools; package Natools.Smaz_Implementations.Base_64 is pragma Pure; procedure Read_Code (Input : in Ada.Streams.Stream_Element_Array; Offset : in out Ada.Streams.Stream_Element_Offset; Code : out Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit; Verbatim_Length : out Natural; Last_Code : in Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit; Variable_Length_Verbatim : in Boolean); procedure Read_Verbatim (Input : in Ada.Streams.Stream_Element_Array; Offset : in out Ada.Streams.Stream_Element_Offset; Output : out String); procedure Skip_Verbatim (Input : in Ada.Streams.Stream_Element_Array; Offset : in out Ada.Streams.Stream_Element_Offset; Verbatim_Length : in Positive); function Verbatim_Size (Input_Length : in Positive; Last_Code : in Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit; Variable_Length_Verbatim : in Boolean) return Ada.Streams.Stream_Element_Count; procedure Write_Code (Output : in out Ada.Streams.Stream_Element_Array; Offset : in out Ada.Streams.Stream_Element_Offset; Code : in Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit); procedure Write_Verbatim (Output : in out Ada.Streams.Stream_Element_Array; Offset : in out Ada.Streams.Stream_Element_Offset; Input : in String; Last_Code : in Natools.Smaz_Implementations.Base_64_Tools.Base_64_Digit; Variable_Length_Verbatim : in Boolean); end Natools.Smaz_Implementations.Base_64; |