123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237(*********************************************************************************)(* OCaml-RDF *)(* *)(* Copyright (C) 2012-2021 Institut National de Recherche en Informatique *)(* et en Automatique. All rights reserved. *)(* *)(* This program is free software; you can redistribute it and/or modify *)(* it under the terms of the GNU Lesser General Public License version *)(* 3 as published by the Free Software Foundation. *)(* *)(* 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 General Public License for more details. *)(* *)(* You should have received a copy of the GNU 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 *)(* *)(* Contact: Maxence.Guesdon@inria.fr *)(* *)(*********************************************************************************)(** *)let()=Random.self_init();;typeliteral={lit_value:string;lit_language:stringoption;lit_type:Iri.toption;}typeblank_id=stringtypeterm=|IriofIri.t|Literalofliteral|Blank|Blank_ofblank_idexceptionInvalid_dateofstringlet()=Printexc.register_printer(function|Invalid_datestr->Some(Printf.sprintf"Invalid date %s"str)|_->None)typetriple=term*Iri.t*termtypedatetime={stamp:Ptime.t;tz:Ptime.tz_offset_soption;}letdatetime_of_stringstr=matchPtime.of_rfc3339strwithOk(stamp,tz,_)->{stamp;tz}|Error(`RFC3339((p1,p2),e))->letb=Buffer.create256inletfmt=Format.formatter_of_bufferbinFormat.fprintffmt"%s\n"str;ifp2>p1thenFormat.fprintffmt"Characters %d-%d: "p1p2elseFormat.fprintffmt"Character %d: "p1;Ptime.pp_rfc3339_errorfmte;Format.pp_print_flushfmt();leterr=Buffer.contentsbinraise(Invalid_dateerr)letstring_of_datetimet=Ptime.to_rfc3339?tz_offset_s:t.tzt.stampletstring_of_blank_idid=id;;letblank_id_of_stringstr=str;;letblankstr=Blank_(blank_id_of_stringstr)letblank_id=Blank_idletterm_of_iri_strings=Iri(Iri.of_strings);;letmk_literal?typ?langv={lit_value=v;lit_language=lang;lit_type=typ;};;letterm_of_literal_string?typ?langv=Literal(mk_literal?typ?langv);;letnow()=matchPtime.of_float_s(Unix.gettimeofday())withNone->assertfalse|Somestamp->{stamp;tz=None}letmk_literal_datetime?(d=now())()=letv=string_of_datetimedinmk_literal~typ:(Iri.of_string"http://www.w3.org/2001/XMLSchema#dateTime")v;;letterm_of_datetime?d()=Literal(mk_literal_datetime?d());;letdatetime_of_literallit=datetime_of_stringlit.lit_valueletmk_literal_boolb=letv=ifbthen"1"else"0"inmk_literal~typ:Rdf_.xsd_booleanv;;letmk_literal_int?(typ=Rdf_.xsd_integer)n=mk_literal~typ(string_of_intn);;letmk_literal_doublef=mk_literal~typ:Rdf_.xsd_double(string_of_floatf);;letterm_of_int?typn=Literal(mk_literal_int?typn)letterm_of_doublef=Literal(mk_literal_doublef)letterm_of_boolb=Literal(mk_literal_boolb);;letbool_of_literallit=matchlit.lit_valuewith"1"|"true"->true|_->false;;(** We must not escape \u sequences used to encode UTF-8 characters.
Since String.escaped escapes all '\\', then unescape "\\u" back to "\u".
*)letunescape_backslash_us=letlen=String.lengthsinletb=Buffer.createleninletreciterp=ifp<len-3thenmatchs.[p],s.[p+1],s.[p+2]with'\\','\\','u'->Buffer.add_stringb"\\u";iter(p+3)|'\\','\\','U'->Buffer.add_stringb"\\U";iter(p+3)|c,_,_->Buffer.add_charbc;iter(p+1)elseifp<lenthen(Buffer.add_charbs.[p];iter(p+1))initer0;Buffer.contentsb;;letquote_strs="\""^(Utf8.utf8_escapes)^"\"";;letstring_of_literallit=(quote_strlit.lit_value)^(matchlit.lit_languagewithNone->""|Somel->"@"^l)^(matchlit.lit_typewithNone->""|Somet->"^^<"^(Iri.to_stringt)^">")letstring_of_term=function|Iriiri->"<"^(Iri.to_stringiri)^">"|Literallit->string_of_literallit|Blank->"_"|Blank_id->"_:"^(string_of_blank_idid);;letpp_termppft=Format.fprintfppf"%s"(string_of_termt)letint64_hashstr=letdigest=Digest.stringstrin(* use the same method as in librdf: use the 8 first bytes to
get a 64 bits integer independant from the little/big endianness *)lethash=refInt64.zeroinfori=0to7dohash:=Int64.add!hash(Int64.shift_left(Int64.of_int(Char.codedigest.[i]))(i*8))done;!hash;;letterm_hash=functionIriiri->int64_hash("R"^(Iri.to_stringiri))|Literallit->int64_hash("L"^lit.lit_value^"<"^(Misc.string_of_optlit.lit_language)^">"^(Misc.string_of_opt(Misc.map_optIri.to_stringlit.lit_type)))|Blank->assertfalse|Blank_id->int64_hash("B"^(string_of_blank_idid));;letcompareterm1term2=matchterm1,term2withIriiri1,Iriiri2->Iri.compareiri1iri2|Iri_,_->1|_,Iri_->-1|Literallit1,Literallit2->beginmatchString.comparelit1.lit_valuelit2.lit_valuewith0->beginmatchMisc.opt_compareString.comparelit1.lit_languagelit2.lit_languagewith0->Misc.opt_compareIri.comparelit1.lit_typelit2.lit_type|n->nend|n->nend|Literal_,_->1|_,Literal_->-1|Blank,Blank->0|Blank,_->1|_,Blank->-1|Blank_id1,Blank_id2->String.compare(string_of_blank_idid1)(string_of_blank_idid2)letequalt1t2=comparet1t2=0moduleOrdered_term=structtypet=termletcompare=compareend;;moduleTSet=Set.Make(Ordered_term);;moduleTMap=Map.Make(Ordered_term);;letlit_true=mk_literal_booltrueletlit_false=mk_literal_boolfalse