1 /* Invisible Vector Library
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 module iv
.ascii85
/*is aliced*/;
26 /// returns input range
27 auto ascii85Decoder(RI
) (auto ref RI src
)
28 if (isInputRange
!RI
&&
29 (isSomeChar
!(ElementType
!RI
)) ||
30 is(ElementType
!RI
: ubyte) ||
31 is(ElementType
!RI
: byte))
35 static immutable uint[5] pow85
= [85*85*85*85u, 85*85*85u, 85*85u, 85u, 1u];
39 static if (isInfinite
!RI
) {
40 enum bool empty
= false;
47 this() (auto ref RI sr
) {
49 static if (!isInfinite
!RI
) isEmpty
= true;
53 popFront
; // populate curCh
57 static if (!isInfinite
!RI
) {
58 @property bool empty () const pure nothrow @nogc { return isEmpty
; }
60 @property ubyte front () const pure nothrow @nogc { return curCh
; }
62 static if (isForwardRange
!RI
) {
63 @property auto save() () {
65 if (!empty
) res
.rng
= rng
.save();
70 // template to allow autodeducing attributes
72 static if (!isInfinite
!RI
) {
73 if (isEmpty
) { curCh
= 0; return; }
80 uint b
= cast(uint)rng
.front
;
82 if (count
== 0 && b
== 'z') {
85 } else if (count
== 0 && b
== 'y') {
89 } else if (b
>= '!' && b
<= 'u') {
90 btuple
+= (b
-'!')*pow85
[count
++];
94 static if (isInfinite
!RI
) {
103 // we have some bytes ready
104 btuple
+= pow85
[--count
];
106 // we have 4 bytes ready
111 curCh
= (btuple
>>24)&0xff;
120 version(test_ascii85
)
123 import std
.utf
: byChar
;
125 immutable e
= `:Ms_p+EVgG/0IE&ARo=s-Z^D?Df'3+B-:f)EZfXGFT`;
126 immutable s
= cast(string
)array(ascii85Decoder(e
.byChar
));
127 //import iv.writer; writeln(s);
128 assert(s
== "One, two, Freddy's coming for you");
132 ":Ms_p+EVgG/0IE&ARo=s-Z^D?Df'3+B-:f)EZfXGFU\n"~
133 "D)]Eb/f5+D,P7E\\&>\"ATW$*EZf1:@r!34Dfp(CA8cC\n"~
134 ",$:\\`QALnsFBm;0OB6%Ei+CQC&Eckl+AncKB$<(MZA\n"~
135 "Ss%AASGdjF=\\P)Df0H$+EMX5Gp%6K+DbJ.AM+<bBl7\n"~
136 "K5+EV14/0I]!G%G\\:F)5E!E$/S%@;0U3/hRJ";
137 immutable s
= cast(string
)array(ascii85Decoder(e
.byChar
));
138 //import iv.writer; writeln(s);
140 "One, two, Freddy's coming for you\n"~
141 "Three, four, Better lock your door\n"~
142 "Five, six, grab a crucifix.\n"~
143 "Seven, eight, Gonna stay up late.\n"~
144 "Nine, ten, Never sleep again...\n");
149 /// returns input range
150 auto ascii85Encoder(RI
) (auto ref RI src
)
151 if (isInputRange
!RI
&&
152 (is(ElementType
!RI
: char) ||
153 is(ElementType
!RI
: ubyte) ||
154 is(ElementType
!RI
: byte)))
161 static if (isInfinite
!RI
) {
162 enum bool empty
= false;
164 bool isEmpty
= false;
169 this() (auto ref RI sr
) {
171 static if (!isInfinite
!RI
) isEmpty
= true;
175 popFront
; // populate curCh
179 static if (!isInfinite
!RI
) {
180 @property bool empty () const pure nothrow @nogc { return isEmpty
; }
181 @property char front () const pure nothrow @nogc { return (isEmpty ?
0 : cast(char)buf
[bpos
]); }
183 @property char front () const pure nothrow @nogc { return cast(char)buf
[bpos
]; }
186 static if (isForwardRange
!RI
) {
187 @property auto save() () {
189 if (!empty
) res
.rng
= rng
.save();
194 // template to allow autodeducing attributes
196 static if (!isInfinite
!RI
) {
204 // read at most 4 bytes and encode 'em
208 if (rng
.empty
) break;
209 auto b
= cast(uint)rng
.front
;
211 btuple |
= b
<<((3-count
)*8);
215 static if (isInfinite
!RI
) {
222 if (count
== 4 && btuple
== 0) {
228 for (bpos
= 0; bpos
< 5; ++bpos
) {
229 buf
[bpos
] = btuple
%85+'!';
232 --bpos
; // current char
240 version(test_ascii85
)
243 import std
.utf
: byChar
;
245 immutable s
= "One, two, Freddy's coming for you";
246 immutable e
= cast(string
)array(ascii85Encoder(s
.byChar
));
247 assert(e
== `:Ms_p+EVgG/0IE&ARo=s-Z^D?Df'3+B-:f)EZfXGFT`);
248 //import iv.writer; writeln(e);
252 "One, two, Freddy's coming for you\n"~
253 "Three, four, Better lock your door\n"~
254 "Five, six, grab a crucifix.\n"~
255 "Seven, eight, Gonna stay up late.\n"~
256 "Nine, ten, Never sleep again...\n";
257 immutable e
= cast(string
)array(ascii85Encoder(s
.byChar
));
259 ":Ms_p+EVgG/0IE&ARo=s-Z^D?Df'3+B-:f)EZfXGFU"~
260 "D)]Eb/f5+D,P7E\\&>\"ATW$*EZf1:@r!34Dfp(CA8cC"~
261 ",$:\\`QALnsFBm;0OB6%Ei+CQC&Eckl+AncKB$<(MZA"~
262 "Ss%AASGdjF=\\P)Df0H$+EMX5Gp%6K+DbJ.AM+<bBl7"~
263 "K5+EV14/0I]!G%G\\:F)5E!E$/S%@;0U3/hRJ");
264 //import iv.writer; writeln(e);