type t = int let _o = 1 let _a = 2 let _w = 4 let _i = 8 let _r = 16 let _O = 32 let _s = 64 let all ts = List.fold_left (lor) 0 ts let filter t u = t land u let of_bitmask_string ?(allowed = 12) s = (* This parameter is a bitmask, with only 2 bits having any signification: if the bit 2 is set, the user mode 'w' will be set and if the bit 3 is set, the user mode 'i' will be set. *) try filter (int_of_string s) allowed with Failure _ -> 0 let of_char = function | 'o' -> _o | 'a' -> _a | 'w' -> _w | 'i' -> _i | 'r' -> _r | 'O' -> _O | 's' -> _s | _ -> 0 let pp ppf t = let f ch = if t land (of_char ch) <> 0 then Format.pp_print_char ppf ch in String.iter f "aiwroOs" let rec of_string_rec s acc i = if i >= String.length s then acc else of_string_rec s (acc lor of_char s.[i]) (i + 1) let of_string s = of_string_rec s 0 0 type diff = int let pp_diff ppf d = if d < 0 then (Format.pp_print_string ppf "-"; pp ppf (-d)) else (Format.pp_print_string ppf "+"; pp ppf d) let ( ~+ ) m = Int.abs m let ( ~- ) m = Int.neg (~+ m) let ( ^ ) t d = if d < 0 then Int.logand (Int.neg d |> Int.lognot) t else Int.logor d t let diff_of_string s = if String.starts_with s ~prefix:"-" then - of_string_rec s 0 1 else + of_string s ;; let%expect_test _ = let print_mode_nl m = Format.kasprintf print_string "%a\n" pp m in print_mode_nl (_O); [%expect {| O |}]; print_mode_nl (all [_o; _a]); [%expect {| ao |}]; print_mode_nl (all [_i; _w; _i]); [%expect {| iw |}]; print_mode_nl (all [_o; _a]); [%expect {| ao |}]; print_mode_nl (all [_o; _a] ^ +_w); [%expect {| awo |}]; print_mode_nl (all [_o; _a; _i] ^ -_o); [%expect {| ai |}]; print_mode_nl (of_string "awrO"); [%expect {| awrO |}]; print_mode_nl (of_string "is"); [%expect {| is |}]; print_mode_nl (of_bitmask_string "0"); [%expect {| |}]; print_mode_nl (of_bitmask_string "4"); [%expect {| w |}]; print_mode_nl (of_bitmask_string "8"); [%expect {| i |}]; print_mode_nl (of_bitmask_string "12"); [%expect {| iw |}];