123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120(* Js_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
* Copyright (C) 2013 Hugo Heuzard
*
* This program 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, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)open!Stdlibletalphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="letcode_rev=leta=Array.make256(-1)infori=0toString.lengthalphabet-1doa.(Char.codealphabet.[i])<-idone;aletin_alphabetx=code_rev.(Char.codex)<>-1letvlq_base_shift=5(* binary: 100000 *)letvlq_base=1lslvlq_base_shift(* binary: 011111 *)letvlq_base_mask=vlq_base-1(* binary: 100000 *)letvlq_continuation_bit=vlq_baselettoVLQSignedv=ifv<0then(-vlsl1)+1elsevlsl1(* assert (toVLQSigned 1 = 2); *)(* assert (toVLQSigned 2 = 4); *)(* assert (toVLQSigned (-1) = 3); *)(* assert (toVLQSigned (-2) = 5);; *)letfromVLQSignedv=letis_neg=vland1=1inletshift=vlsr1inifis_negthen-shiftelseshift(* assert (fromVLQSigned 2 = 1); *)(* assert (fromVLQSigned 4 = 2); *)(* assert (fromVLQSigned 3 = -1); *)(* assert (fromVLQSigned 5 = -2);; *)letadd_charbufx=Buffer.add_charbufalphabet.[x]letrecencode'bufx=letdigit=xlandvlq_base_maskinletrest=xlsrvlq_base_shiftinifrest=0thenadd_charbufdigitelse(add_charbuf(digitlorvlq_continuation_bit);encode'bufrest)letencodebx=letvql=toVLQSignedxinencode'bvqlletencode_lbl=List.iter~f:(encodeb)lletrecdecode'accsstartpos=letdigit=code_rev.(Char.codes.[pos])inifdigit=-1theninvalid_arg"Vql64.decode'";letcont=digitlandvlq_continuation_bit=vlq_continuation_bitinletdigit=digitlandvlq_base_maskinletacc=acc+(digitlsl((pos-start)*vlq_base_shift))inifcontthendecode'accsstart(succpos)elseacc,succposletdecodesp=letd,i=decode'0sppinfromVLQSignedd,iletdecode_ls~pos~len=letrecauxposacclen=iflen=0thenList.revaccelseiflen<0theninvalid_arg"Vlq64.decode_l"elseletd,i=decodesposinletlen=len-(i-pos)inauxi(d::acc)leninauxpos[]lentypeinput={string:string;mutablepos:int;len:int}letrecdecode'srcsposlenoffseti=ifpos=lentheninvalid_arg"Vql64.decode'";letdigit=Array.unsafe_getcode_rev(Char.codes.[pos])inifdigit=-1theninvalid_arg"Vql64.decode'";leti=i+((digitlandvlq_base_mask)lsloffset)inifdigit>=vlq_continuation_bitthendecode'srcs(pos+1)len(offset+vlq_base_shift)ielse(src.pos<-pos+1;i)letdecodesrc=fromVLQSigned(decode'srcsrc.stringsrc.possrc.len00)