Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
metadataBase.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
(** Raised when the format is invalid. *) exception Invalid type bigarray = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t type metadata = (string * string) list type endianness = Big_endian | Little_endian type parser_handler = { label : string; length : int; read : unit -> string; read_ba : (unit -> bigarray) option; skip : unit -> unit; } type custom_parser = parser_handler -> unit module Reader = struct (** A function to read taking the buffer to fill the offset and the length and returning the number of bytes actually read. *) type t = { read : bytes -> int -> int -> int; read_ba : (int -> bigarray) option; custom_parser : custom_parser option; seek : int -> unit; size : unit -> int option; reset : unit -> unit; } (** Make a reading function retry until buffer is filled (or an error occurs). *) let retry read buf off len = let r = ref 0 in let loop = ref true in while !loop do let n = read buf (off + !r) (len - !r) in r := !r + n; loop := !r <> 0 && !r < len && n <> 0 done; !r let read f n = let s = Bytes.create n in let k = retry f.read s 0 n in if k <> n then raise Invalid; Bytes.unsafe_to_string s let read_tag ~length ~label f = let is_custom = match f.custom_parser with | None -> false | Some custom_parser -> let is_custom = ref false in let skip () = is_custom := true; f.seek length in let read () = is_custom := true; read f length in let read_ba = Option.map (fun read_ba () -> is_custom := true; read_ba length) f.read_ba in custom_parser { read_ba; read; skip; length; label }; !is_custom in if is_custom then None else Some (read f length) let drop f n = f.seek n let byte f = int_of_char (read f 1).[0] let uint8 f = byte f let int16_be f = let b0 = byte f in let b1 = byte f in (b0 lsl 8) + b1 let int16_le f = let b0 = byte f in let b1 = byte f in (b1 lsl 8) + b0 let uint16_le = int16_le let int16 = function Big_endian -> int16_be | Little_endian -> int16_le let int24_be f = let b0 = byte f in let b1 = byte f in let b2 = byte f in (b0 lsl 16) + (b1 lsl 8) + b2 let int32_le f = let b0 = byte f in let b1 = byte f in let b2 = byte f in let b3 = byte f in (b3 lsl 24) + (b2 lsl 16) + (b1 lsl 8) + b0 let uint32_le = int32_le let int32_be f = let b0 = byte f in let b1 = byte f in let b2 = byte f in let b3 = byte f in (b0 lsl 24) + (b1 lsl 16) + (b2 lsl 8) + b3 let size f = f.size () let reset f = f.reset () let with_file ?custom_parser f fname = let fd = Unix.openfile fname [Unix.O_RDONLY; Unix.O_CLOEXEC] 0o644 in let file = let read = Unix.read fd in let read_ba len = let pos = Int64.of_int (Unix.lseek fd 0 Unix.SEEK_CUR) in let ba = Bigarray.array1_of_genarray (Unix.map_file ~pos fd Bigarray.char Bigarray.c_layout false [| len |]) in ignore (Unix.lseek fd len Unix.SEEK_CUR); ba in let seek n = ignore (Unix.lseek fd n Unix.SEEK_CUR) in let size () = try let p = Unix.lseek fd 0 Unix.SEEK_CUR in let n = Unix.lseek fd 0 Unix.SEEK_END in ignore (Unix.lseek fd p Unix.SEEK_SET); Some n with _ -> None in let reset () = ignore (Unix.lseek fd 0 Unix.SEEK_SET) in { read; read_ba = Some read_ba; seek; size; reset; custom_parser } in try let ans = f file in Unix.close fd; ans with e -> let bt = Printexc.get_raw_backtrace () in Unix.close fd; Printexc.raise_with_backtrace e bt let with_string ?custom_parser f s = let len = String.length s in let pos = ref 0 in let read b ofs n = let n = min (len - !pos) n in String.blit s !pos b ofs n; pos := !pos + n; n in let seek n = pos := !pos + n in let reset () = pos := 0 in let size () = Some len in f { read; read_ba = None; seek; size; reset; custom_parser } end module Int = struct include Int let find p = let ans = ref 0 in try while true do if p !ans then raise Exit else incr ans done; assert false with Exit -> !ans end