123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148(*
* Base64 - Base64 codec
* Copyright (C) 2003 Nicolas Cannasse
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)exceptionInvalid_charexceptionInvalid_table(* UNUSED exception Invalid_padding *)externalunsafe_char_of_int:int->char="%identity"typeencoding_table=chararraytypedecoding_table=intarrayletchars=[|'A';'B';'C';'D';'E';'F';'G';'H';'I';'J';'K';'L';'M';'N';'O';'P';'Q';'R';'S';'T';'U';'V';'W';'X';'Y';'Z';'a';'b';'c';'d';'e';'f';'g';'h';'i';'j';'k';'l';'m';'n';'o';'p';'q';'r';'s';'t';'u';'v';'w';'x';'y';'z';'0';'1';'2';'3';'4';'5';'6';'7';'8';'9';'+';'/'|]letmake_decoding_tabletbl=ifArray.lengthtbl <>64thenraiseInvalid_table;letd=Array.make256(-1)infori=0to63doArray.unsafe_setd(int_of_char(Array.unsafe_gettbli))i;done;dlet inv_chars=make_decoding_tablecharsletencode?(tbl=chars)ch=ifArray.lengthtbl<>64thenraiseInvalid_table;letdata =ref0inletcount=ref0inletflush()=if!count>0thenbeginletd=(!datalsl(6-!count))land63inBatIO.writech(Array.unsafe_gettbld);end;count:=0;inletwritec=letc=int_of_charcindata:=(!datalsl8)lorc;count:=!count+8;while !count>=6docount:=!count -6;let d=(!data asr!count)land63inBatIO.writech(Array.unsafe_gettbld)done;inletoutputspl=fori=ptop+l-1dowrite(Bytes.unsafe_getsi)done;linBatIO.create_out~write~output~flush:(fun ()->flush();BatIO.flushch)~close:(fun()->flush();BatIO.close_outch)letdecode?(tbl=inv_chars)ch=ifArray.lengthtbl<>256thenraiseInvalid_table;letdata =ref0inletcount=ref0inletrecfetch()=if!count>=8thenbegincount:=!count-8;let d=(!data asr!count)land0xFFinunsafe_char_of_int dendelseletc=int_of_char(BatIO.readch)inletc=Array.unsafe_gettblcinifc=-1then raiseInvalid_char;data :=(!datalsl6)lorc;count :=!count+6;fetch()inletread=fetch inletinputspl=leti=ref0intrywhile!i<ldoBytes.unsafe_sets(p+!i)(fetch());incri;done;lwithBatIO.No_more_inputwhen!i>0->!iinletclose()=count:=0;BatIO.close_inchinBatIO.create_in~read~input~closeletstr_encode?(tbl=chars)s=letch=encode~tbl(BatIO.output_string())inBatIO.nwritech s;BatIO.close_outchletstr_decode?(tbl=inv_chars)s=letch=decode~tbl(BatIO.input_strings)inBatIO.nreadch((String.lengths*6)/8)(*$Q str_decode; str_encode
(Q.string) (fun s -> s = str_decode (str_encode s))
(Q.string) (fun s -> let e = str_encode s in e = str_encode (str_decode e))
*)(*$T make_decoding_table
try ignore (make_decoding_table [|'1'|]); false \
with Invalid_table -> true
try ignore (make_decoding_table (Array.make 2000 '1')); false \
with Invalid_table -> true
*)(*$T str_encode
try ignore (str_encode ~tbl:[|'1'|] "mlk"); false \
with Invalid_table -> true
try ignore (str_encode ~tbl:(Array.make 2000 '1') "mlk"); false \
with Invalid_table -> true
*)(*$T str_decode
try ignore (str_decode ~tbl:[|1|] "mlk"); false \
with Invalid_table -> true
try ignore (str_decode ~tbl:(Array.make 2000 1) "mlk"); false \
with Invalid_table -> true
*)