123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592(**************************************************************************)(* *)(* Typerex Libraries *)(* *)(* Copyright 2011-2017 OCamlPro SAS *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)(* Currently, we have no distinction between implicit and .-relative
filenames. We should probably do that.
*)openEzCompat(* IMPORTANT OS specificities (from the JDK):
Each filename is composed of:
- an optional prefix:
nothing
/ root on Unix for absolute filenames
\ root on Windows for absolute filenames without drive
\\ UNC filename
c: drive on Windows for relative filenames
c:\ root and drive on windows for absolute filenames
(nothing on Unix or c: or C: on Windows or \)
- a list of basenames (possibly empty for the root )
- there is an official separator like \ or /
- there is an official path-separator like : (unix) or ; (windows)
- listRoots() returns the list of available drives
- getAbsolutePath() -> absolute path
- getCanonicalPath() -> absolute path simplified and without symlinks
*)(*
[file_dir] points to the parent directory, unless when it points back to
the file itself, which happens for:
* the File.t is a root directory, with [file_basename] equals "/" or "\\"
* the File.t is the current directory, with [file_basename] equals "."
* the File.t is the parent directory, with [file_basename] equals ".."
* the File.t is implicit
*)typet={file_basename:string;file_dir:t;file_string:string;(* The system filename, i.e. with system-specific separators *)file_partition:string;}letroot_basename=FileOS.dir_separator_stringletbasenamet=t.file_basenameletrecis_absolutet=ift.file_dir!=tthenis_absolutet.file_direlset.file_basename=root_basenameletis_relativet=not(is_absolutet)letis_implicitt=ift.file_dir==tthenmatcht.file_basenamewith|"/"|"\\"->false|_->trueelseletrecitert=ift.file_dir!=tthenitert.file_direlsematcht.file_basenamewith|"."|".."|"/"|"\\"->false|_->trueinitert.file_dir(*
let to_root_dir t =
let rec root = {
file_dir = root;
file_basename = root_basename;
file_partition = t.file_partition;
file_string = t.file_partition ^ root_basename;
} in
root
*)letto_empty_dirt=letrecroot={file_dir=root;file_basename="";file_partition=t.file_partition;file_string=t.file_partition;}inrootletto_current_dirt=letrecroot={file_dir=root;file_basename=".";file_partition=t.file_partition;file_string=t.file_partition^".";}inrootletto_parent_dirt=letrecroot={file_dir=root;file_basename="..";file_partition=t.file_partition;file_string=t.file_partition^"..";}inroot(*
let rec to_string_raw t =
if t.file_dir == t then
Printf.sprintf "[%s]" t.file_basename
else
Printf.sprintf "%s::%s" (to_string_raw t.file_dir) t.file_basename
*)letto_stringt=t.file_string(* ^ "=" ^ to_string_raw t *)letdirnamet=ift.file_dir==tthenmatcht.file_basenamewith|"/"|"\\"|"."->t|_->to_current_dirtelset.file_dirletadd_basename_stringdirbasename=matchdir.file_basenamewith|""|"/"|"\\"->dir.file_partition^dir.file_basename^basename|_->dir.file_string^FileOS.dir_separator_string^basenameletadd_basename_simpledirbasename={file_basename=basename;file_dir=dir;file_partition=dir.file_partition;file_string=add_basename_stringdirbasename;}letadd_basenamedirbasename=matchdir.file_basename,basenamewith|"..",".."->add_basename_simpledirbasename|(""|"."),".."->to_parent_dirdir|("/"|"\\"),".."->dir|_,".."->ifdir.file_dir==dirthento_empty_dirdirelsedir.file_dir|_,("."|"/"|"\\"|"")->dir|_->add_basename_simpledirbasenameletrecadd_basenamesdirlist=matchlistwith[]->dir|(""|".")::tail->add_basenamesdirtail|basename::tail->add_basenames(add_basenamedirbasename)tailletconcatt1t2=(*
if t1.file_partition <> "" &&
t2.file_partition <> "" &&
t1.file_partition <> t2.file_partition then
failwith "Filename2.concat: filenames have different partitions";
if is_absolute t2 then
failwith "Filename2.concat: second filename is absolute";
*)letreciterdirt=letdir=ift.file_dir!=ttheniterdirt.file_direlsedirinadd_basenamedirt.file_basenameinitert1t2letcheck_suffixfilesuffix=Filename.check_suffixfile.file_basenamesuffixletadd_suffixtsuffix=matcht.file_basenamewith"."|".."|""->failwith"Filename2.add_extension: symbolic file"|_->ift.file_dir==tthenletrecroot={file_basename=t.file_basename^suffix;file_partition=t.file_partition;file_dir=root;file_string=t.file_string^suffix;}inrootelse{file_basename=t.file_basename^suffix;file_partition=t.file_partition;file_dir=t.file_dir;file_string=t.file_string^suffix;}(* utilities for [of_string] *)letrecnormalize_pathpath=matchpathwith[]->[]|dir::tail->letdir=dir::normalize_pathtailinmatchdirwith|""::path->path|"."::path->path|".."::_->dir|_::".."::path->path|_->dirletrecremove_leading_dotdotspath=matchpathwith".."::path->remove_leading_dotdotspath|_->pathletrecmakedirpath=matchpathwith[]->dir|basename::tail->lett={file_basename=basename;file_dir=dir;file_partition=dir.file_partition;file_string=add_basename_stringdirbasename;}inmakettailtypekind=|Absolute|Current|Parent|Relativeletof_pathpartpath=letkind=matchpathwith|""::_::_->Absolute|"."::_->Current|".."::_->Parent|_->Relativeinletpath=normalize_pathpathinletpath=ifkind=Absolutethenremove_leading_dotdotspathelsepathinifkind=Absolutethenletrecroot={file_basename=FileOS.dir_separator_string;file_dir=root;file_string=part^FileOS.dir_separator_string;file_partition=part;}inmakerootpathelsematchpathwith[]->beginmatchkindwith|Current|Relative->letbasename=ifkind=Currentthen"."else""inletreccurrent_dir={file_basename=basename;file_dir=current_dir;file_string=part^basename;file_partition=part;}incurrent_dir|_->assertfalseend|dir::tail->letrecbase_dir={file_basename=dir;file_dir=base_dir;file_partition=part;file_string=part^dir;}inmakebase_dirtailletof_unix_strings=letpath=EzString.splits'/'inletpart=""inof_pathpartpathletof_win32_strings=lets1,s2=EzString.cut_ats':'inletss=ifs1==sthenselses2inletss=String.map(function'/'->'\\'|c->c)ssinletpart=ifs1==sthen""else(String.lowercases1)^":"inletpath=EzString.splitss'\\'inof_pathpartpathletof_strings=ifFileOS.win32thenof_win32_stringselseof_unix_stringsletadd_pathdirpath=concatdir(of_stringpath)(*
let () =
let root_dir = of_unix_string "/" in
let current_dir = of_unix_string "." in
let parent_dir = of_unix_string ".." in
let empty_dir = of_unix_string "" in
let relative_dir = add_basename current_dir "foo" in
let parrel_dir = add_basename parent_dir "foo" in
let absolute_dir = add_basename root_dir "foo" in
let implicit_dir = of_unix_string "foo" in
let relative_dir2 = add_basenames current_dir ["foo"; "bar"] in
let parrel_dir2 = add_basenames parent_dir ["foo"; "bar" ] in
let absolute_dir2 = add_basenames root_dir ["foo"; "bar"] in
let implicit_dir2 = add_basename (of_unix_string "foo") "bar" in
let parrel_dir3 = add_basenames parent_dir [".."; "foo"; "bar" ] in
let oc = open_out "file.result" in
let test_to_string d =
Printf.fprintf oc "[%s]\n%!" (to_string d)
in
let test_is_absolute d =
Printf.fprintf oc "is_absolute(%s) = %b\n%!"
(to_string d) (is_absolute d)
in
let test_is_relative d =
Printf.fprintf oc "is_relative(%s) = %b\n%!"
(to_string d) (is_relative d)
in
let test_is_implicit d =
Printf.fprintf oc "is_implicit(%s) = %b\n%!"
(to_string d) (is_implicit d)
in
let test_concat d1 d2 =
Printf.fprintf oc "concat [%s] [%s] = %!"
(to_string d1) (to_string d2);
try
let f = concat d1 d2 in
Printf.fprintf oc "[%s]\n%!" (to_string f)
with exn ->
Printf.fprintf oc "%s\n%!" (Printexc.to_string exn);
in
let dirs = [ root_dir;
current_dir;
parent_dir;
empty_dir;
relative_dir;
absolute_dir;
implicit_dir;
parrel_dir;
relative_dir2;
absolute_dir2;
implicit_dir2;
parrel_dir2;
parrel_dir3;
] in
List.iter test_to_string dirs;
List.iter test_is_absolute dirs;
List.iter test_is_relative dirs;
List.iter test_is_implicit dirs;
List.iter (fun d1 ->
List.iter (test_concat d1) dirs) dirs;
close_out oc;
assert (to_string root_dir = "/");
assert (to_string current_dir = ".");
assert (to_string parent_dir = "..");
assert (to_string relative_dir = "./foo");
assert (to_string absolute_dir = "/foo");
assert (to_string implicit_dir = "foo");
assert (to_string empty_dir = "");
assert (to_string relative_dir2 = "./foo/bar");
assert (to_string absolute_dir2 = "/foo/bar");
assert (to_string implicit_dir2 = "foo/bar");
assert (is_absolute root_dir);
assert (not (is_absolute current_dir));
assert (not (is_absolute parent_dir));
assert (not (is_absolute relative_dir));
assert (is_absolute absolute_dir);
assert (not (is_absolute empty_dir));
assert (not (is_absolute implicit_dir));
assert (not (is_relative root_dir));
assert (is_relative current_dir);
assert (is_relative parent_dir);
assert (is_relative relative_dir);
assert (not (is_relative absolute_dir));
assert (is_relative empty_dir); (* different from Filename.is_relative "" *)
assert (is_relative implicit_dir);
()
*)(**************************************************************************)(* *)(* Typerex Libraries *)(* *)(* Copyright 2011-2017 OCamlPro SAS *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)letwith_infilenamef=FileString.with_in(to_stringfilename)fletwith_in_binfilenamef=FileString.with_in_bin(to_stringfilename)fletwith_outfilenamef=FileString.with_out(to_stringfilename)fletwith_out_binfilenamef=FileString.with_out_bin(to_stringfilename)fletread_sublinesfileofflen=FileString.read_sublines(to_stringfile)offlenletread_sublines_to_listfileofflen=FileString.read_sublines_to_list(to_stringfile)offlenletiteri_linesffile=FileString.iteri_linesf(to_stringfile)letiter_linesffile=FileString.iter_linesf(to_stringfile)letwrite_filefiles=FileString.write_file(to_stringfile)sletread_filefile=FileString.read_file(to_stringfile)letwrite_linesfilelines=FileString.write_lines(to_stringfile)linesletwrite_lines_of_listfilelines=FileString.write_lines_of_list(to_stringfile)linesletread_linesfile=FileString.lines_of_file(to_stringfile)letread_lines_to_listfile=FileString.read_lines_to_list(to_stringfile)letread_lines_to_revlistfile=FileString.read_lines_to_revlist(to_stringfile)letread_subfilefileposlen=FileString.read_subfile(to_stringfile)poslenletstring_of_subfile=read_subfileletfile_of_lines=write_linesletlines_of_file=read_linesletstring_of_file=read_fileletfile_of_string=write_fileletrenamet1t2=Sys.rename(to_stringt1)(to_stringt2)letexistsfile=Sys.file_exists(to_stringfile)letis_directoryfilename=trylets=MinUnix.stat(to_stringfilename)ins.MinUnix.st_kind=MinUnix.S_DIRwith_->falseletis_linkfile=FileString.is_link(to_stringfile)letsizefile=FileString.size(to_stringfile)letstatfilename=MinUnix.stat(to_stringfilename)letlstatfilename=MinUnix.lstat(to_stringfilename)letgetcwd()=of_string(Sys.getcwd())(*
let size64 filename =
let s = MinUnix.LargeFile.stat (to_string filename) in
s.MinUnix.LargeFile.st_size
*)letopen_infilename=open_in(to_stringfilename)letopen_outfilename=open_out(to_stringfilename)letopen_in_binfilename=open_in_bin(to_stringfilename)letopen_out_binfilename=open_out_bin(to_stringfilename)letcopy_filef1f2=FileString.copy_file(to_stringf1)(to_stringf2)letopen_fdfilemodeperm=MinUnix.openfile(to_stringfile)modepermletremovefile=Sys.remove(to_stringfile)letiter_blocksffile=FileString.iter_blocksf(to_stringfile)(*let safe_mkdir ?mode dir = FileString.safe_mkdir ?mode (to_string dir) *)letcopy_recsrcdst=FileString.copy_rec(to_stringsrc)(to_stringdst)letuncopy_recsrcdst=FileString.uncopy_rec(to_stringsrc)(to_stringdst)(*
let last_extension file =
FileString.last_extension (basename file)
let chop_extension f =
let (basename, _ext) = EzString.cut_at f.file_basename '.' in
let ext_len = String.length f.file_basename - String.length basename in
if ext_len = 0 then f else
let len = String.length f.file_string in
{ f with
file_basename = basename;
file_string = String.sub f.file_string 0 (len-ext_len);
}
*)letequalt1t2=t1.file_string=t2.file_string&&t1.file_partition=t2.file_partitionlettemp_filetext=of_string(Filename.temp_file(to_stringt)ext)letcurrent_dir_name=of_string"."letto_rooted_stringt=ifis_absolutetthent.file_stringelsePrintf.sprintf".%c%s"FileOS.dir_separatort.file_string(*
module String = FileString
module Lines = FileLines
module Channel = FileChannel
module OS = FileOS
*)(*
let safe_basename s =
basename (of_string s)
*)moduleOP=structlet(//)ts=add_basenamest(EzString.splits'/')endmoduleDirectory_operations=FileDirMaker.Make(structtypepath=tletto_string=to_stringletadd_basename=add_basenameletdirname=dirnameletbasename=basenameletrmdirs=MinUnix.rmdir(to_strings)letlstats=MinUnix.lstat(to_strings)letstats=MinUnix.stat(to_strings)letmkdirsperm=MinUnix.mkdir(to_strings)permletremoves=Sys.remove(to_strings)letreaddirs=Sys.readdir(to_strings)end)includeDirectory_operationsletfind_in_pathpathname=letfile=of_stringnameinifnot(is_implicitfile)thenifexistsfilethenfileelseraiseNot_foundelseletrectry_dir=function[]->raiseNot_found|dir::rem->letdir=of_stringdirinletfullname=concatdirfileinifexistsfullnamethenfullnameelsetry_dirremintry_dirpathletcut_extensionfile=letbasename=basenamefileinletbasename,extensions=EzString.cut_atbasename'.'inletextensions=String.lowercaseextensionsin(basename,extensions)letcut_extensionsfile=let(basename,extensions)=cut_extensionfileinletextensions=EzString.splitextensions'.'in(basename,extensions)