123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416(*
Copyright 2012-2025 Codinuum Software Lab <https://codinuum.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*)(* source_base.ml *)[%%prepare_logger]moduleXchannel=Diffast_misc.XchannelmoduleStorage=Diffast_misc.StoragemoduleLoc=Astlocletarray_set=Array.unsafe_setletbytes_get=Bytes.unsafe_getletbytes_fill=Bytes.unsafe_fillletbytes_blit=Bytes.unsafe_blitletbytes_to_string=Bytes.unsafe_to_stringtypeencoding=|E_Latin1|E_UTF8|E_UTF16BE|E_UTF16LEletdefault_encoding=E_UTF8letencoding_to_string=function|E_Latin1->"Latin1"|E_UTF8->"UTF8"|E_UTF16BE->"UTF16BE"|E_UTF16LE->"UTF16LE"letinternal_ubuf_size=512letlinefeed=Uchar.of_int0xaletchar_to_strc=String.escaped(Printf.sprintf"%c"c)letuchar_to_struc=ifUchar.is_charucthenchar_to_str(Uchar.to_charuc)elsePrintf.sprintf"U+%X;"(Uchar.to_intuc)let_=bytes_to_stringlet_=uchar_to_strmoduleLatin1=structletcheck_length_=1letget_ucharbufi=Uchar.utf_decode1(Uchar.of_char(bytes_getbufi))letis_valid_utf_=trueletutf_byte_length_=1letmax_bytes_per_uchar=1end[%%capture_pathmoduleUtf8=structletcheck_lengthc=(* derive length from head char *)letb=Char.codecinletlen=ifbland0b10000000=0then1elseifbland0b11100000=0b11000000then2elseifbland0b11110000=0b11100000then3elseifbland0b11111000=0b11110000then4elseinvalid_arg"Utf8.check_length"in[%debug_log"c='%s' b=%#x %#o (%d) len=%d"(char_to_strc)bbblen];lenletget_uchar=Bytes.get_utf_8_ucharletis_valid_utf=Bytes.is_valid_utf_8letutf_byte_length=Uchar.utf_8_byte_lengthletmax_bytes_per_uchar=4end][%%capture_pathmoduleUtf16=structletcheck_lengthc=(* derive length from head char *)letb=Char.codecinletlen=ifbland0b11111100=0b11011000then4else2in[%debug_log"c='%s' b=%#x %#o (%d) len=%d"(char_to_strc)bbblen];lenmoduleBE=structletget_uchar=Bytes.get_utf_16be_ucharletis_valid_utf=Bytes.is_valid_utf_16beendmoduleLE=structletget_uchar=Bytes.get_utf_16le_ucharletis_valid_utf=Bytes.is_valid_utf_16leendletutf_byte_length=Uchar.utf_16_byte_lengthletmax_bytes_per_uchar=4end][%%capture_pathclassc(file:Storage.file)=lettree=file#treeinletpath=file#pathinobject(self)valpos_mgr=newPosition.managerpathvalmutableeof_reached=falsevalmutableeof_loc:Loc.toption=Nonevalmutablechannel=Nonevalmutableencoding=default_encodingvalmutableutf_check_length=Utf8.check_lengthvalmutableget_uchar=Utf8.get_ucharvalmutableis_valid_utf=Utf8.is_valid_utfvalmutableutf_byte_length=Utf8.utf_byte_lengthvalmutablemax_bytes_per_uchar=Utf8.max_bytes_per_ucharvalmutableulexbuf_list=[]valmutableeof_flag=falsevalmutableinternal_buf_size=internal_ubuf_size*4valmutableinternal_buf=Bytes.create(internal_ubuf_size*4)valinternal_ubuf=Array.makeinternal_ubuf_sizeUchar.minvalmutablelast_uchar=Uchar.minvalmutablebytes_decoded=0valmutablelast_bytes=0methodupdate_encoding?(update_buf=true)enc=encoding<-enc;beginmatchencwith|E_Latin1->beginutf_check_length<-Latin1.check_length;get_uchar<-Latin1.get_uchar;is_valid_utf<-Latin1.is_valid_utf;utf_byte_length<-Latin1.utf_byte_length;max_bytes_per_uchar<-Latin1.max_bytes_per_uchar;end|E_UTF8->beginutf_check_length<-Utf8.check_length;get_uchar<-Utf8.get_uchar;is_valid_utf<-Utf8.is_valid_utf;utf_byte_length<-Utf8.utf_byte_length;max_bytes_per_uchar<-Utf8.max_bytes_per_uchar;end|E_UTF16BE->beginutf_check_length<-Utf16.check_length;get_uchar<-Utf16.BE.get_uchar;is_valid_utf<-Utf16.BE.is_valid_utf;utf_byte_length<-Utf16.utf_byte_length;max_bytes_per_uchar<-Utf16.max_bytes_per_uchar;end|E_UTF16LE->beginutf_check_length<-Utf16.check_length;get_uchar<-Utf16.LE.get_uchar;is_valid_utf<-Utf16.LE.is_valid_utf;utf_byte_length<-Utf16.utf_byte_length;max_bytes_per_uchar<-Utf16.max_bytes_per_uchar;endend;ifupdate_bufthenbegininternal_buf_size<-internal_ubuf_size*max_bytes_per_uchar;internal_buf<-Bytes.createinternal_buf_sizeendmethodtree=treemethodpath=pathmethodinit=pos_mgr#resetmethodeof_reached=eof_reachedmethodset_eof_reached=eof_reached<-truemethodeof_loc=eof_locmethodset_eof_locloc=eof_loc<-Somelocmethodfile=filemethodfilename=pos_mgr#filenamemethodset_filenamefn=pos_mgr#set_filenamefnmethodpos_mgr=pos_mgrmethodexists=file#existsmethodget_channel=letch=trytree#get_channelself#filenamewithSys_errors->failwith("Source_base.c#get_channel: "^s)inchmethodget_ulexbuf_from_channelch=letulexbuf=Sedlexing.create~bytes_per_char:utf_byte_length(self#refillch)inSedlexing.set_filenameulexbufself#filename;ulexbuf_list<-ulexbuf::ulexbuf_list;ulexbufmethodget_ulexbuf=letch=self#get_channelinchannel<-Somech;self#get_ulexbuf_from_channelchmethodclose=matchchannelwith|Somech->beginch#close();[%debug_log"%s closed"path]end|None->()methodget_ulexbuf_from_stdin=matchencodingwith|E_Latin1->Sedlexing.Latin1.from_channelstdin|E_UTF8->Sedlexing.Utf8.from_channelstdin|E_UTF16BE->Sedlexing.Utf16.from_channelstdin(SomeSedlexing.Utf16.Big_endian)|E_UTF16LE->Sedlexing.Utf16.from_channelstdin(SomeSedlexing.Utf16.Little_endian)methodprivateread_uchar()=letdec=letdec=get_ucharinternal_bufbytes_decodedinifUchar.utf_decode_is_validdecthenbeginbegin%trace_blockletc=bytes_getinternal_bufbytes_decodedinletb=Char.codecin[%trace_log"bytes_decoded=%d '%s' %#x %#o (%d)"bytes_decoded(char_to_strc)bbb]end;decendelsebeginletc=bytes_getinternal_bufbytes_decodedinlet_=cinbegin%trace_blockletb=Char.codecin[%trace_log"decode failed: bytes_decoded=%d '%s' %#x %#o (%d)"bytes_decoded(char_to_strc)bbb]end;[%warn_log"[%s] invalid character '%s'"(encoding_to_stringencoding)(char_to_strc)];[%warn_log"falling back to latin1 encoding"];self#update_encoding~update_buf:falseE_Latin1;get_ucharinternal_bufbytes_decodedendinletuc=Uchar.utf_decode_uchardecin[%trace_log"uc=%s"(uchar_to_struc)];ucmethodrefillchubufposn=[%debug_log"|ubuf|=%d pos=%d n=%d"(Array.lengthubuf)posn];try[%debug_log"bytes_decoded=%d last_bytes=%d"bytes_decodedlast_bytes];letreq_size,ofs=ifbytes_decoded<last_bytesthenbeginletbbuf=Bytes.createinternal_buf_sizeinletrem=last_bytes-bytes_decodedinbytes_blitinternal_bufbytes_decodedbbuf0rem;internal_buf<-bbuf;internal_buf_size-rem,remendelseinternal_buf_size,0in[%debug_log"ofs=%d req_size=%d"ofsreq_size];letbytes_read=ch#inputinternal_bufofsreq_sizeinlast_bytes<-ofs+bytes_read;[%debug_log"internal_buf_size=%d bytes_read=%d last_bytes=%d"internal_buf_sizebytes_readlast_bytes];iflast_bytes=0thenbeginifeof_flagthen0elsebegin[%debug_log"last_uchar='%s'"(uchar_to_strlast_uchar)];ifUchar.equallast_ucharlinefeedthen0elsebegineof_flag<-true;array_setubufposlinefeed;1endendendelsebeginiflast_bytes<internal_buf_sizethenbeginletd=min3(internal_buf_size-last_bytes)inbytes_fillinternal_buflast_bytesd'\000'end;[%debug_log"internal_buf=%s"(bytes_to_stringinternal_buf)];bytes_decoded<-0;letnc=ref0inletline_len=ref0inwhile!nc<n&&bytes_decoded<last_bytesdo[%trace_log"bytes_decoded=%d nc=%d"bytes_decoded!nc];(*let d = last_bytes - bytes_decoded in
if d < 3 then begin
[%debug_log "bytes_decoded=%d d=%d" bytes_decoded d];
try
let blen = utf_check_length (bytes_get internal_buf bytes_decoded) in
[%debug_log "blen=%d" blen];
if blen > 1 then begin
if blen > d then begin
let blen_ = blen - d in
[%debug_log "reading %d more bytes" blen_];
let actual_blen = ch#input internal_buf (bytes_decoded + 1) blen_ in
let _ = actual_blen in
[%debug_log "actual_blen=%d" actual_blen]
end
end
with Invalid_argument _ -> ()
end;*)letuc=(self#read_uchar[@inlined])()inifUchar.equaluclinefeedthenbeginpos_mgr#feedline(!line_len+1);line_len:=-1end;array_setubuf(pos+!nc)uc;last_uchar<-uc;letuc_len=utf_byte_lengthucin[%trace_log"uc_len=%d"uc_len];bytes_decoded<-bytes_decoded+uc_len;incrnc;incrline_lendone;if!line_len>0thenpos_mgr#feed!line_len;begin%debug_blockletcbuf=Buffer.create0infori=postopos+!nc-1doletc=ubuf.(i)inifUchar.is_charcthenBuffer.add_charcbuf(Uchar.to_charc)elseBuffer.add_charcbuf'?'done;[%debug_log"ubuf[%d:%d]=%s"pos(pos+!nc)(Buffer.contentscbuf)];end;[%debug_log"nc=%d"!nc];!ncendwith|End_of_file->0(*| exc -> begin
[%warn_log "\"%s\": %s: \"%s\""
file#fullpath (Printexc.to_string exc) (bytes_to_string internal_buf)];
failwith ("Source_base.c#refill: " ^ (Printexc.to_string exc))
end*)end(* of class Sourcefile_base.c *)]