diff --git a/doc/content/xapi/cli/_index.md b/doc/content/xapi/cli/_index.md index 6715e7288c0..093e1576aaf 100644 --- a/doc/content/xapi/cli/_index.md +++ b/doc/content/xapi/cli/_index.md @@ -156,7 +156,7 @@ So each function receives a printer for sending text output to the xe client, an let mac = List.assoc_default "mac" params "" in let network = Client.Network.get_by_uuid rpc session_id network in let pifs = List.assoc "pif-uuids" params in - let uuids = String.split ',' pifs in + let uuids = String.split_on_char ',' pifs in let pifs = List.map (fun uuid -> Client.PIF.get_by_uuid rpc session_id uuid) uuids in let mode = Record_util.bond_mode_of_string (List.assoc_default "mode" params "") in let properties = read_map_params "properties" params in diff --git a/ocaml/database/parse_db_conf.ml b/ocaml/database/parse_db_conf.ml index 67aa5c70d80..d1c7482c080 100644 --- a/ocaml/database/parse_db_conf.ml +++ b/ocaml/database/parse_db_conf.ml @@ -13,7 +13,6 @@ *) (* !!! This needs to be moved out of xapi and into the database directory; probably being merged with db_connections !!! *) -open Xapi_stdext_std.Xstringext open Xapi_stdext_unix module D = Debug.Make (struct let name = "parse_db_conf" end) @@ -110,7 +109,7 @@ let parse_db_conf s = let conf = Unixext.string_of_file s in let lines : string list ref = ref [] in let consume_line () = lines := List.tl !lines in - lines := String.split '\n' conf ; + lines := String.split_on_char '\n' conf ; List.iter (fun line -> debug "%s" line) !lines ; let read_block () = let path_line = List.hd !lines in @@ -120,7 +119,7 @@ let parse_db_conf s = while !lines <> [] && List.hd !lines <> "" do let line = List.hd !lines in key_values := - ( match String.split ':' line with + ( match String.split_on_char ':' line with | k :: vs -> ( String.lowercase_ascii k , String.lowercase_ascii (String.concat ":" vs) diff --git a/ocaml/database/redo_log.ml b/ocaml/database/redo_log.ml index 8c2c95928d7..42175580f83 100644 --- a/ocaml/database/redo_log.ml +++ b/ocaml/database/redo_log.ml @@ -12,7 +12,6 @@ * GNU Lesser General Public License for more details. *) open Xapi_stdext_pervasives.Pervasiveext -open Xapi_stdext_std.Xstringext open Xapi_stdext_unix let with_lock = Xapi_stdext_threads.Threadext.Mutex.execute diff --git a/ocaml/doc/dune b/ocaml/doc/dune index 061ba778232..618de9e30fb 100644 --- a/ocaml/doc/dune +++ b/ocaml/doc/dune @@ -1,7 +1,7 @@ (executable (modes exe) (name jsapi) - (libraries + (libraries mustache rpclib.core rpclib.json @@ -10,7 +10,6 @@ xapi-consts xapi-datamodel xapi-stdext-pervasives - xapi-stdext-std xapi-stdext-unix ) (preprocess (pps ppx_deriving_rpc)) diff --git a/ocaml/doc/jsapi.ml b/ocaml/doc/jsapi.ml index fa891e57743..1fef7fabf00 100644 --- a/ocaml/doc/jsapi.ml +++ b/ocaml/doc/jsapi.ml @@ -12,7 +12,6 @@ * GNU Lesser General Public License for more details. *) -open Xapi_stdext_std.Xstringext open Xapi_stdext_pervasives.Pervasiveext module Unixext = Xapi_stdext_unix.Unixext open Datamodel_types diff --git a/ocaml/idl/markdown_backend.ml b/ocaml/idl/markdown_backend.ml index ca067ef9dcb..3125d850b85 100644 --- a/ocaml/idl/markdown_backend.ml +++ b/ocaml/idl/markdown_backend.ml @@ -43,41 +43,41 @@ let compare_case_ins x y = compare (String.lowercase_ascii x) (String.lowercase_ascii y) let escape s = - let esc_char = function + let replace = function | '\\' -> - "\" + Some "\" | '*' -> - "*" + Some "*" | '_' -> - "_" + Some "_" | '{' -> - "{" + Some "{" | '}' -> - "}" + Some "}" | '[' -> - "[" + Some "[" | ']' -> - "]" + Some "]" | '(' -> - "(" + Some "(" | ')' -> - ")" + Some ")" | '>' -> - ">" + Some ">" | '<' -> - "<" + Some "<" | '#' -> - "#" + Some "#" | '+' -> - "+" + Some "+" | '-' -> - "-" + Some "-" | '!' -> - "!" - | c -> - String.make 1 c + Some "!" + | _ -> + None in - String.to_seq s |> Seq.map esc_char |> List.of_seq |> String.concat "" + Xapi_stdext_std.Xstringext.String.replaced ~replace s let rec of_ty_verbatim = function | SecretString | String -> diff --git a/ocaml/idl/ocaml_backend/gen_rbac.ml b/ocaml/idl/ocaml_backend/gen_rbac.ml index 7914dba96dd..ad17e10db5f 100644 --- a/ocaml/idl/ocaml_backend/gen_rbac.ml +++ b/ocaml/idl/ocaml_backend/gen_rbac.ml @@ -70,11 +70,10 @@ let role_uuid name = Option.get (hash2uuid name) let permission_description = "A basic permission" let permission_name wire_name = - let open Xapi_stdext_std in let s1 = replace_char (Printf.sprintf "permission_%s" wire_name) '.' '_' in let s2 = replace_char s1 '/' '_' in - let s3 = Xstringext.String.replace "*" "WILDCHAR" s2 in - Xstringext.String.replace ":" "_" s3 + let s3 = Xapi_stdext_std.Xstringext.String.replace '*' ~by:"WILDCHAR" s2 in + replace_char s3 ':' '_' let permission_index = ref 0 diff --git a/ocaml/libs/http-lib/dune b/ocaml/libs/http-lib/dune index 4e8d255b6bd..ac6db1b23d4 100644 --- a/ocaml/libs/http-lib/dune +++ b/ocaml/libs/http-lib/dune @@ -63,6 +63,7 @@ xapi-backtrace xapi-log xapi-stdext-pervasives + xapi-stdext-std xapi-stdext-threads xapi-stdext-unix)) diff --git a/ocaml/libs/http-lib/http_svr.ml b/ocaml/libs/http-lib/http_svr.ml index 7c5ecc393d1..6271c5ad987 100644 --- a/ocaml/libs/http-lib/http_svr.ml +++ b/ocaml/libs/http-lib/http_svr.ml @@ -331,28 +331,22 @@ module Server = struct x.handlers [] end -let escape uri = - (* from xapi-stdext-std xstringext *) - let escaped ~rules string = - let aux h t = - ( if List.mem_assoc h rules then - List.assoc h rules - else - Astring.String.of_char h +let escape_html uri = + Xapi_stdext_std.Xstringext.String.replaced + ~replace:(function + | '<' -> + Some "<" + | '>' -> + Some ">" + | '\'' -> + Some "'" + | '"' -> + Some """ + | '&' -> + Some "&" + | _ -> + None ) - :: t - in - String.concat "" (Astring.String.fold_right aux string []) - in - escaped - ~rules: - [ - ('<', "<") - ; ('>', ">") - ; ('\'', "'") - ; ('"', """) - ; ('&', "&") - ] uri exception Generic_error of string @@ -508,7 +502,7 @@ let read_request ?proxy_seen ~read_timeout ~total_timeout ~max_length fd = ) | exc -> response_internal_error exc fd - ~extra:(escape (Printexc.to_string exc)) + ~extra:(escape_html (Printexc.to_string exc)) ) ; (None, None) @@ -557,7 +551,7 @@ let handle_one (x : 'a Server.t) ss context req = ) | exc -> response_internal_error ~req exc ss - ~extra:(escape (Printexc.to_string exc)) + ~extra:(escape_html (Printexc.to_string exc)) ) ; !finished diff --git a/ocaml/libs/http-lib/http_svr.mli b/ocaml/libs/http-lib/http_svr.mli index 61b49e7b3f2..cf335592d7b 100644 --- a/ocaml/libs/http-lib/http_svr.mli +++ b/ocaml/libs/http-lib/http_svr.mli @@ -68,6 +68,9 @@ val start : val handle_one : 'a Server.t -> Unix.file_descr -> 'a -> Http.Request.t -> bool +val escape_html : string -> string +(** Escapes HTML: replaces characters with their character references *) + exception Socket_not_found val stop : socket -> unit diff --git a/ocaml/libs/sexpr/sExpr.ml b/ocaml/libs/sexpr/sExpr.ml index 3637ac6abf5..c9794265d49 100644 --- a/ocaml/libs/sexpr/sExpr.ml +++ b/ocaml/libs/sexpr/sExpr.ml @@ -28,7 +28,7 @@ let is_escape_char = function '\\' | '\'' -> true | _ -> false (* XXX: This escapes "'c'" and "\'c\'" to "\\'c\\'". * They are both unescaped as "'c'". They have been ported * to make sure that this corner case is left unchanged. - * It is worth investigating the use of + * It is worth investigating the use of * - Astring.String.Ascii.escape_string * - Astring.String.Ascii.unescape * that have guaranteed invariants and optimised performances *) diff --git a/ocaml/libs/tgroup/dune b/ocaml/libs/tgroup/dune index 6c152a5c2ef..12070176651 100644 --- a/ocaml/libs/tgroup/dune +++ b/ocaml/libs/tgroup/dune @@ -2,7 +2,7 @@ (name tgroup) (modules tgroup) (public_name tgroup) - (libraries unix xapi-log xapi-stdext-unix xapi-stdext-std)) + (libraries astring unix xapi-log xapi-stdext-unix)) (test (name test_tgroup) diff --git a/ocaml/libs/tgroup/tgroup.ml b/ocaml/libs/tgroup/tgroup.ml index 071a9dfe0d2..e5b163fea60 100644 --- a/ocaml/libs/tgroup/tgroup.ml +++ b/ocaml/libs/tgroup/tgroup.ml @@ -70,8 +70,7 @@ module Group = struct | _ -> false - let sanitize s = - Xapi_stdext_std.Xstringext.String.filter_chars s is_alphanum + let sanitize s = Astring.String.filter is_alphanum s let make ?user_agent subject_sid = let user_agent = diff --git a/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/bench/bench_xstringext.ml b/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/bench/bench_xstringext.ml index 52897ee2a0c..d302737b1b1 100644 --- a/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/bench/bench_xstringext.ml +++ b/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/bench/bench_xstringext.ml @@ -8,36 +8,42 @@ let make_string len = String.init len (fun i -> Char.chr (33 + (i mod 94))) let escape_rules = [('a', "[A]"); ('e', "[E]"); ('i', "[I]"); ('o', "[O]"); ('u', "[U]")] -(* Reference implementation from xstringext_test.ml *) -let escaped_spec ?rules string = - match rules with - | None -> - String.escaped string - | Some rules -> - let apply_rules char = - match List.assoc_opt char rules with - | None -> - Seq.return char - | Some replacement -> - String.to_seq replacement - in - string |> String.to_seq |> Seq.concat_map apply_rules |> String.of_seq +let replace = function + | 'a' -> + Some "[A]" + | 'e' -> + Some "[E]" + | 'i' -> + Some "[I]" + | 'o' -> + Some "[O]" + | 'u' -> + Some "[U]" + | _ -> + None + +(* Reference implementation using lists *) +let replaced_spec ~rules string = + let apply_rules char = List.assoc_opt char rules in + XString.replaced ~replace:apply_rules string -let escaped_benchmark n = +let replaced ~rules string = XString.replaced ~replace:rules string + +let replaced_benchmark n = let s = make_string n in - Staged.stage @@ fun () -> ignore (XString.escaped ~rules:escape_rules s) + Staged.stage @@ fun () -> ignore (replaced ~rules:replace s) -let escaped_spec_benchmark n = +let replaced_spec_benchmark n = let s = make_string n in - Staged.stage @@ fun () -> ignore (escaped_spec ~rules:escape_rules s) + Staged.stage @@ fun () -> ignore (replaced_spec ~rules:escape_rules s) -let test_escaped = - Test.make_indexed ~name:"escaped" ~fmt:"%s %d" ~args:[100; 500; 1000] - escaped_benchmark +let test_replaced = + Test.make_indexed ~name:"replaced" ~fmt:"%s %d" ~args:[100; 500; 1000] + replaced_benchmark -let test_escaped_spec = - Test.make_indexed ~name:"escaped-spec" ~fmt:"%s %d" ~args:[100; 500; 1000] - escaped_spec_benchmark +let test_replaced_spec = + Test.make_indexed ~name:"replaced-spec" ~fmt:"%s %d" ~args:[100; 500; 1000] + replaced_spec_benchmark let benchmark () = let ols = @@ -50,8 +56,8 @@ let benchmark () = Benchmark.cfg ~limit:2000 ~quota:(Time.second 0.5) ~kde:(Some 1000) () in let test = - Test.make_grouped ~name:"escaped-comparison" - [test_escaped; test_escaped_spec] + Test.make_grouped ~name:"replaced-comparison" + [test_replaced; test_replaced_spec] in let raw_results = Benchmark.all cfg instances test in let results = @@ -97,8 +103,10 @@ let () = List.iter (fun size -> Printf.printf "String size %s:\n" size ; - let opt_test = Printf.sprintf "escaped-comparison/escaped %s" size in - let ref_test = Printf.sprintf "escaped-comparison/escaped-spec %s" size in + let opt_test = Printf.sprintf "replaced-comparison/replaced %s" size in + let ref_test = + Printf.sprintf "replaced-comparison/replaced-spec %s" size + in match (get_timing opt_test, get_timing ref_test) with | Some opt_time, Some ref_time -> let improvement = (ref_time -. opt_time) /. ref_time *. 100.0 in diff --git a/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext.ml b/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext.ml index 4e5379d7b36..854245b9b6d 100644 --- a/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext.ml +++ b/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext.ml @@ -12,79 +12,18 @@ * GNU Lesser General Public License for more details. *) module String = struct - include String - - let of_char c = String.make 1 c - - let rev_map f string = - let n = length string in - String.init n (fun i -> f string.[n - i - 1]) - - let rev_iter f string = - for i = length string - 1 downto 0 do - f string.[i] - done - - let fold_left f accu string = - let accu = ref accu in - for i = 0 to length string - 1 do - accu := f !accu string.[i] - done ; - !accu - - let fold_right f string accu = - let accu = ref accu in - for i = length string - 1 downto 0 do - accu := f string.[i] !accu - done ; - !accu - - (** Returns true for whitespace characters, false otherwise *) - let isspace = function ' ' | '\n' | '\r' | '\t' -> true | _ -> false - - let split_f p str = - let split_one seq = - let not_p c = not (p c) in - let a = Seq.take_while not_p seq in - let b = Seq.drop_while not_p seq in - (a, b) - in - let drop seq = Seq.drop_while p seq in - let rec split acc chars = - if Seq.is_empty chars then - acc - else - let a, b = split_one chars in - let b = drop b in - let acc = if Seq.is_empty a then acc else Seq.cons a acc in - split acc b - in - String.to_seq str - |> split Seq.empty - |> Seq.map String.of_seq - |> List.of_seq - |> List.rev - - let index_opt s c = - let rec loop i = - if String.length s = i then - None - else if s.[i] = c then - Some i - else - loop (i + 1) - in - loop 0 + let sub_to_end s start = + let length = String.length s in + String.sub s start (length - start) - let rec split ?(limit = -1) c s = - let i = match index_opt s c with Some x -> x | None -> -1 in - let nlimit = if limit = -1 || limit = 0 then limit else limit - 1 in - if i = -1 || nlimit = 0 then - [s] - else - let a = String.sub s 0 i - and b = String.sub s (i + 1) (String.length s - i - 1) in - a :: split ~limit:nlimit c b + let rec split ~limit sep s = + match (String.index_opt s sep, limit < 2) with + | None, _ | _, true -> + [s] + | Some pos, false -> + let first = String.sub s 0 pos in + let rest = sub_to_end s (pos + 1) in + first :: split ~limit:(limit - 1) sep rest let rtrim s = let n = String.length s in @@ -93,71 +32,6 @@ module String = struct else s - (** has_substr str sub returns true if sub is a substring of str. Simple, naive, slow. *) - let has_substr str sub = - if String.length sub > String.length str then - false - else - let result = ref false in - for start = 0 to String.length str - String.length sub do - if String.sub str start (String.length sub) = sub then result := true - done ; - !result - - (** find all occurences of needle in haystack and return all their respective index *) - let find_all needle haystack = - let m = String.length needle and n = String.length haystack in - if m > n then - [] - else - let i = ref 0 and found = ref [] in - while !i < n - m + 1 do - if String.sub haystack !i m = needle then ( - found := !i :: !found ; - i := !i + m - ) else - incr i - done ; - List.rev !found - - (* replace all @f substring in @s by @t *) - let replace f t s = - let indexes = find_all f s in - let n = List.length indexes in - if n > 0 then ( - let len_f = String.length f and len_t = String.length t in - let new_len = String.length s + (n * len_t) - (n * len_f) in - let new_b = Bytes.make new_len '\000' in - let orig_offset = ref 0 and dest_offset = ref 0 in - List.iter - (fun h -> - let len = h - !orig_offset in - Bytes.blit_string s !orig_offset new_b !dest_offset len ; - Bytes.blit_string t 0 new_b (!dest_offset + len) len_t ; - orig_offset := !orig_offset + len + len_f ; - dest_offset := !dest_offset + len + len_t - ) - indexes ; - Bytes.blit_string s !orig_offset new_b !dest_offset - (String.length s - !orig_offset) ; - Bytes.unsafe_to_string new_b - ) else - s - - let filter_chars s valid = - let badchars = ref false in - let buf = Buffer.create 0 in - for i = 0 to String.length s - 1 do - if !badchars then ( - if valid s.[i] then - Buffer.add_char buf s.[i] - ) else if not (valid s.[i]) then ( - Buffer.add_substring buf s 0 i ; - badchars := true - ) - done ; - if !badchars then Buffer.contents buf else s - let map_unlikely s f = let changed = ref false in let m = ref 0 in @@ -178,18 +52,10 @@ module String = struct ) else s - let escaped ?rules s = - match rules with - | None -> - String.escaped s - | Some rules -> - map_unlikely s (fun c -> List.assoc_opt c rules) - - let sub_to_end s start = - let length = String.length s in - String.sub s start (length - start) - - let sub_before c s = String.sub s 0 (String.index s c) + let replace char ~by s = + let replaceable = Stdlib.Char.equal char in + let get_replacement c = if replaceable c then Some by else None in + map_unlikely s get_replacement - let sub_after c s = sub_to_end s (String.index s c + 1) + let replaced ~replace s = map_unlikely s replace end diff --git a/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext.mli b/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext.mli index 1f27490493d..62a1053d883 100644 --- a/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext.mli +++ b/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext.mli @@ -12,63 +12,21 @@ * GNU Lesser General Public License for more details. *) module String : sig - include module type of String + val replaced : replace:(char -> string option) -> string -> string + (** [replaced ~replacement str] applies [replace] to all characters in [str] + and when it returns [Some rep] the character is replaced with [rep] in + the resulting string *) - val of_char : char -> string + val replace : char -> by:string -> string -> string + (** [replace ch ~by s] replaces all the occurrences of [ch] in [s] by [~by] + *) - val rev_map : (char -> char) -> string -> string - (** Map a string to a string, applying the given function in reverse - order. *) - - val rev_iter : (char -> unit) -> string -> unit - (** Iterate over the characters in a string in reverse order. *) - - val fold_left : ('a -> char -> 'a) -> 'a -> string -> 'a - (** Fold over the characters in a string. *) - - val fold_right : (char -> 'a -> 'a) -> string -> 'a -> 'a - (** Iterate over the characters in a string in reverse order. *) - - val isspace : char -> bool - (** True if the character is whitespace *) - - val escaped : ?rules:(char * string) list -> string -> string - (** Backward-compatible string escaping, defaulting to the built-in - OCaml string escaping but allowing an arbitrary mapping from characters - to strings. *) - - val split_f : (char -> bool) -> string -> string list - (** Take a predicate and a string, return a list of strings separated by - runs of characters where the predicate was true. Avoid if possible, it's - very costly to execute. *) - - val split : ?limit:int -> char -> string -> string list + val split : limit:int -> char -> string -> string list (** split a string on a single char *) val rtrim : string -> string (** FIXME document me|remove me if similar to strip *) - val has_substr : string -> string -> bool - (** True if sub is a substr of str *) - - val find_all : string -> string -> int list - (** find all occurences of needle in haystack and return all their respective index *) - - val replace : string -> string -> string -> string - (** replace all [f] substring in [s] by [t] *) - - val filter_chars : string -> (char -> bool) -> string - (** filter chars from a string *) - - val map_unlikely : string -> (char -> string option) -> string - (** map a string trying to fill the buffer by chunk *) - val sub_to_end : string -> int -> string (** a substring from the specified position to the end of the string *) - - val sub_before : char -> string -> string - (** a substring from the start of the string to the first occurrence of a given character, excluding the character *) - - val sub_after : char -> string -> string - (** a substring from the first occurrence of a given character to the end of the string, excluding the character *) end diff --git a/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext_test.ml b/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext_test.ml index 9b7eb2674a1..4fe39225785 100644 --- a/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext_test.ml +++ b/ocaml/libs/xapi-stdext/lib/xapi-stdext-std/xstringext_test.ml @@ -13,10 +13,6 @@ module XString = Xapi_stdext_std.Xstringext.String -let test_boolean tested_f (name, case, expected) = - let check () = Alcotest.(check bool) name expected (tested_f case) in - (name, `Quick, check) - let test_string tested_f (name, case, expected) = let check () = Alcotest.(check string) name expected (tested_f case) in (name, `Quick, check) @@ -27,47 +23,14 @@ let test_list tested_f (name, case, expected) = in (name, `Quick, check) -let test_rev_map = - let spec_rev = [("", ""); ("foo bar", "rab oof")] in - let spec_func = [("id", Fun.id); ("uppercase_ascii", Char.uppercase_ascii)] in - let test (f_name, f) (case, expected) = - let expected = String.map f expected in - let name = - Printf.sprintf {|"%s" produces "%s" (%s)|} case expected f_name - in - test_string (XString.rev_map f) (name, case, expected) - in - let tests = - (* Generate the product of the two lists to generate the tests *) - List.concat_map (fun func -> List.map (test func) spec_rev) spec_func - in - ("rev_map", tests) - let test_split = - let test ?limit (splitter, splitted, expected) = - let split, name = - match limit with - | None -> - let name = Printf.sprintf {|'%c' splits "%s"|} splitter splitted in - (* limit being set to -1 is the same as not using the parameter *) - let split = XString.split ~limit:(-1) in - (split, name) - | Some limit -> - let name = - Printf.sprintf {|'%c' splits "%s" with limit %i|} splitter splitted - limit - in - let split = XString.split ~limit in - (split, name) + let test limit (splitter, splitted, expected) = + let split = XString.split ~limit in + let name = + Printf.sprintf {|'%c' splits "%s" with limit %i|} splitter splitted limit in test_list (split splitter) (name, splitted, expected) in - let specs_no_limit = - [ - ('.', "...", [""; ""; ""; ""]); ('.', "foo.bar.baz", ["foo"; "bar"; "baz"]) - ] - in - let tests_no_limit = List.map test specs_no_limit in let specs_limit = [ (0, [('.', "...", ["..."]); ('.', "foo.bar.baz", ["foo.bar.baz"])]) @@ -82,50 +45,12 @@ let test_split = ; (4, [('.', "...", [""; ""; ""; ""])]) ] in - let tests_limit = + let tests = List.concat_map - (fun (limit, spec) -> List.map (test ~limit) spec) + (fun (limit, spec) -> List.map (test limit) spec) specs_limit in - ("split", List.concat [tests_no_limit; tests_limit]) - -let test_split_f = - let specs = - [ - (XString.isspace, "foo bar", ["foo"; "bar"]) - ; (XString.isspace, "foo bar", ["foo"; "bar"]) - ; (XString.isspace, "foo \n\t\r bar", ["foo"; "bar"]) - ; (XString.isspace, " foo bar ", ["foo"; "bar"]) - ; (XString.isspace, "", []) - ; (XString.isspace, " ", []) - ] - in - let test (splitter, splitted, expected) = - let name = Printf.sprintf {|"%s"|} (String.escaped splitted) in - test_list (XString.split_f splitter) (name, splitted, expected) - in - let tests = List.map test specs in - ("split_f", tests) - -let test_has_substr = - let spec = - [ - ("", "", true) - ; ("", "foo bar", true) - ; ("f", "foof", true) - ; ("foofo", "foof", false) - ; ("foof", "foof", true) - ; ("f", "foof", true) - ; ("fo", "foof", true) - ; ("of", "foof", true) - ; ("ff", "foof", false) - ] - in - let test (contained, container, expected) = - let name = Printf.sprintf {|"%s" in "%s"|} contained container in - test_boolean (XString.has_substr container) (name, contained, expected) - in - ("has_substr", List.map test spec) + ("split", tests) let test_rtrim = let spec = @@ -147,49 +72,4 @@ let test_rtrim = in ("rtrim", List.map test spec) -(** Simple implementation of escaped for testing against *) -let escaped_spec ?rules string = - match rules with - | None -> - String.escaped string - | Some rules -> - let apply_rules char = - match List.assoc_opt char rules with - | None -> - Seq.return char - | Some replacement -> - String.to_seq replacement - in - string |> String.to_seq |> Seq.concat_map apply_rules |> String.of_seq - -let test_escaped = - let open QCheck2 in - (* Generator for escape rules: list of (char, string) mappings *) - let gen_rules = - let open Gen in - let gen_rule = pair char (string_size (int_range 0 5) ~gen:char) in - list gen_rule - in - (* Generator for test input: string and optional rules *) - let gen_input = Gen.pair Gen.string (Gen.opt gen_rules) in - let property (s, rules) = - let expected = escaped_spec ?rules s in - let actual = XString.escaped ?rules s in - String.equal expected actual - in - let test = - Test.make ~name:"escaped matches reference implementation" ~count:1000 - gen_input property - in - ("escaped", [QCheck_alcotest.to_alcotest test]) - -let () = - Alcotest.run "Xstringext" - [ - test_rev_map - ; test_split - ; test_split_f - ; test_has_substr - ; test_rtrim - ; test_escaped - ] +let () = Alcotest.run "Xstringext" [test_split; test_rtrim] diff --git a/ocaml/quicktest/quicktest_http.ml b/ocaml/quicktest/quicktest_http.ml index 0320cf12ab3..d718a61a9e7 100644 --- a/ocaml/quicktest/quicktest_http.ml +++ b/ocaml/quicktest/quicktest_http.ml @@ -34,7 +34,7 @@ module Uds = struct with_channel_aux fd func let http_response_code d = - match Xapi_stdext_std.Xstringext.String.split ' ' d with + match String.split_on_char ' ' d with | _ :: code :: _ -> int_of_string code | _ -> @@ -99,7 +99,7 @@ module Cookies = struct match body with | first_line :: _ -> D.warn "expected = [%s]; received = [%s]" expected first_line ; - Xapi_stdext_std.Xstringext.String.has_substr first_line expected + Astring.String.is_infix ~affix:first_line expected | _ -> false in @@ -210,9 +210,7 @@ module HTML_Escaping = struct let bad_command_exp = "<>'\\"&" let html_escaping expected cmd = - let check_result b = - Xapi_stdext_std.Xstringext.String.has_substr b expected - in + let check_result = Astring.String.is_infix ~affix:expected in let _, _, _, body = Uds.http_command Xapi_globs.unix_domain_socket cmd in match body with | first_line :: _ -> diff --git a/ocaml/rrd2csv/src/rrd2csv.ml b/ocaml/rrd2csv/src/rrd2csv.ml index 37e00f8148d..bb57fbbb8d3 100644 --- a/ocaml/rrd2csv/src/rrd2csv.ml +++ b/ocaml/rrd2csv/src/rrd2csv.ml @@ -149,10 +149,10 @@ module Ds_selector = struct let of_string str = let open Rrd in - let splitted = Xstringext.String.split ',' str in + let splitted = String.split_on_char ',' str in match splitted with | without_trailing_comma :: _ -> ( - let splitted = Xstringext.String.split ':' without_trailing_comma in + let splitted = String.split_on_char ':' without_trailing_comma in match splitted with | [cf; owner; uuid; metric] -> { @@ -185,14 +185,7 @@ module Ds_selector = struct let escape_metric s = let quote s = Printf.sprintf "\"%s\"" s in if String.contains s '"' then - quote - (Xstringext.String.map_unlikely s (function - | '\"' -> - Some "\"\"" - | _ -> - None - ) - ) + quote (Xstringext.String.replace '"' ~by:{|""|} s) else if String.contains s ',' || String.contains s '\n' then quote s else diff --git a/ocaml/tests/test_guest_agent.ml b/ocaml/tests/test_guest_agent.ml index 6bc0f227c7b..94774ac10c7 100644 --- a/ocaml/tests/test_guest_agent.ml +++ b/ocaml/tests/test_guest_agent.ml @@ -42,9 +42,7 @@ module Networks = Generic.MakeStateless (struct ) let construct_tree tree path = - let nodes = - Xapi_stdext_std.Xstringext.String.split_f (fun s -> s = '/') path - in + let nodes = Astring.String.cuts ~empty:false ~sep:"/" path in add_path_to_tree tree nodes let rec list_helper children = function @@ -60,9 +58,7 @@ module Networks = Generic.MakeStateless (struct ) let list (T (_root, children)) path = - let nodes = - Xapi_stdext_std.Xstringext.String.split_f (fun s -> s = '/') path - in + let nodes = Astring.String.cuts ~empty:false ~sep:"/" path in list_helper children nodes let transform input = @@ -231,9 +227,7 @@ module Initial_guest_metrics = Generic.MakeStateless (struct ) let construct_mtree mtree (path, leaf_value) = - let nodes = - Xapi_stdext_std.Xstringext.String.split_f (fun s -> s = '/') path - in + let nodes = Astring.String.cuts ~empty:false ~sep:"/" path in add_leaf_to_mtree nodes leaf_value mtree let rec list_helper children = function @@ -254,9 +248,7 @@ module Initial_guest_metrics = Generic.MakeStateless (struct | Lf (_, _) -> [] | Mt (_, children) -> - let nodes = - Xapi_stdext_std.Xstringext.String.split_f (fun s -> s = '/') path - in + let nodes = Astring.String.cuts ~empty:false ~sep:"/" path in list_helper children nodes let rec lookup_helper mtree = function @@ -274,9 +266,7 @@ module Initial_guest_metrics = Generic.MakeStateless (struct ) let lookup mtree path = - let nodes = - Xapi_stdext_std.Xstringext.String.split_f (fun s -> s = '/') path - in + let nodes = Astring.String.cuts ~empty:false ~sep:"/" path in lookup_helper mtree nodes let transform input = diff --git a/ocaml/xapi-cli-server/cli_printer.ml b/ocaml/xapi-cli-server/cli_printer.ml index 1fc1d5586fd..bb627812924 100644 --- a/ocaml/xapi-cli-server/cli_printer.ml +++ b/ocaml/xapi-cli-server/cli_printer.ml @@ -47,9 +47,15 @@ let rec multi_line_record r = (* Used to escape commas in --minimal mode *) let escape_commas x = - (* Escaping rules: *) - let rules = [(',', "\\,"); (* , -> \, *) ('\\', "\\\\") (* \ -> \\ *)] in - Xapi_stdext_std.Xstringext.String.escaped ~rules x + let replace = function + | ',' -> + Some "\\," + | '\\' -> + Some "\\\\" + | _ -> + None + in + Xapi_stdext_std.Xstringext.String.replaced ~replace x let make_printer sock minimal = let buffer = ref [] in diff --git a/ocaml/xapi/audit_log.ml b/ocaml/xapi/audit_log.ml index 0563b2c4fe3..473df72f39e 100644 --- a/ocaml/xapi/audit_log.ml +++ b/ocaml/xapi/audit_log.ml @@ -102,12 +102,8 @@ let transfer_all_audit_files fd_out ?filter since = atransfer_try_gz "" (* map the ISO8601 timestamp format into the one in our logs *) -let log_timestamp_of_iso8601 iso8601_timestamp = - let module Xstringext = Xapi_stdext_std.Xstringext in - let step1 = iso8601_timestamp in - let step2 = Xstringext.String.replace "-" "" step1 in - let step3 = Xstringext.String.replace "Z" "" step2 in - step3 +let log_timestamp_of_iso8601 iso8601 = + Astring.String.filter (function '-' | 'Z' -> false | _ -> true) iso8601 (* Assume that RBAC access for the session_id already verified by xapi_http.ml diff --git a/ocaml/xapi/authx.ml b/ocaml/xapi/authx.ml index 87d85e40332..7236c793fb4 100644 --- a/ocaml/xapi/authx.ml +++ b/ocaml/xapi/authx.ml @@ -65,7 +65,7 @@ module AuthX : Auth_signature.AUTH_MODULE = struct | [] -> raise Not_found | line :: lines -> ( - let recs = Xapi_stdext_std.Xstringext.String.split ':' line in + let recs = String.split_on_char ':' line in let username = List.nth recs 0 in let uid = List.nth recs 2 in match fn username uid recs with @@ -291,9 +291,8 @@ module AuthX : Auth_signature.AUTH_MODULE = struct | _ -> raise Not_found - (* - In addition, there are some event hooks that auth modules implement as follows: -*) + (* In addition, there are some event hooks that auth modules implement as + follows: *) (* unit on_enable(((string*string) list) config_params) diff --git a/ocaml/xapi/config_file_sync.ml b/ocaml/xapi/config_file_sync.ml index b765f1ceae6..cf877745290 100644 --- a/ocaml/xapi/config_file_sync.ml +++ b/ocaml/xapi/config_file_sync.ml @@ -15,7 +15,6 @@ module D = Debug.Make (struct let name = "config_file_sync" end) open D -open Xapi_stdext_std.Xstringext let superuser = "root" @@ -58,7 +57,8 @@ let config_file_sync_handler (req : Http.Request.t) s _ = Xapi_http.with_context "Syncing dom0 config files over HTTP" req s (fun __context -> let uri = - String.split '/' req.Http.Request.path |> List.filter (fun x -> x <> "") + String.split_on_char '/' req.Http.Request.path + |> List.filter (fun x -> x <> "") in req.Http.Request.close <- true ; debug "sending headers" ; diff --git a/ocaml/xapi/dbsync_slave.ml b/ocaml/xapi/dbsync_slave.ml index ff325b7259e..ea5dddf8f82 100644 --- a/ocaml/xapi/dbsync_slave.ml +++ b/ocaml/xapi/dbsync_slave.ml @@ -17,7 +17,6 @@ *) module Rrdd = Rrd_client.Client -open Xapi_stdext_std.Xstringext module Unixext = Xapi_stdext_unix.Unixext module Date = Clock.Date open Create_misc @@ -75,9 +74,9 @@ let get_start_time () = match Unixext.string_of_file "/proc/stat" |> String.trim - |> String.split '\n' + |> String.split_on_char '\n' |> List.find (fun s -> String.starts_with ~prefix:"btime" s) - |> String.split ' ' + |> String.split_on_char ' ' with | _ :: btime :: _ -> let boot_time = Date.of_unix_time (float_of_string btime) in @@ -111,7 +110,7 @@ let refresh_localhost_info ~__context info = | None -> [] | Some {capabilities; _} -> - String.split ' ' capabilities + String.split_on_char ' ' capabilities in Db.Host.set_capabilities ~__context ~self:host ~value:caps ; Db.Host.set_address ~__context ~self:host ~value:(get_my_ip_addr ~__context) ; diff --git a/ocaml/xapi/extauth_plugin_ADpbis.ml b/ocaml/xapi/extauth_plugin_ADpbis.ml index ea2dedfccc6..b57b2c91cae 100644 --- a/ocaml/xapi/extauth_plugin_ADpbis.ml +++ b/ocaml/xapi/extauth_plugin_ADpbis.ml @@ -18,7 +18,7 @@ module D = Debug.Make (struct let name = "extauth_plugin_ADpbis" end) open D -open Xapi_stdext_std.Xstringext +module Stringext = Xapi_stdext_std.Xstringext.String let ( let@ ) = ( @@ ) @@ -92,6 +92,8 @@ module Lwsmd = struct ) end +let is_word_sep = function '(' | ')' | ' ' | '\t' | '.' -> true | _ -> false + let match_error_tag (lines : string list) = let err_catch_list = [ @@ -105,8 +107,7 @@ let match_error_tag (lines : string list) = ] in let split_to_words str = - let seps = ['('; ')'; ' '; '\t'; '.'] in - String.split_f (fun s -> List.exists (fun sep -> sep = s) seps) str + Astring.String.fields ~empty:false ~is_sep:is_word_sep str in let rec has_err lines err_pattern = match lines with @@ -131,9 +132,11 @@ let match_error_tag (lines : string list) = let extract_sid_from_group_list group_list = List.map (fun (_, v) -> - let v = String.replace ")" "" v in - let v = String.replace "sid =" "|" v in - let vs = String.split_f (fun c -> c = '|') v in + let vs = + Astring.String.filter (function ')' -> false | _ -> true) v + |> Astring.String.cuts ~empty:false ~sep:"sid =" + |> List.concat_map (Astring.String.cuts ~empty:false ~sep:"|") + in let sid = String.trim (List.nth vs 1) in debug "extract_sid_from_group_list get sid=[%s]" sid ; sid @@ -166,7 +169,8 @@ module AuthADlw : Auth_signature.AUTH_MODULE = struct Locking_helpers.Named_mutex.create "IS_SERVER_AVAILABLE" let splitlines s = - String.split_f (fun c -> c = '\n') (String.replace "#012" "\n" s) + Astring.String.cuts ~empty:false ~sep:"#012" s + |> List.concat_map (Astring.String.cuts ~empty:false ~sep:"\n") let pbis_common_with_password (password : string) (pbis_cmd : string) (pbis_args : string list) = @@ -238,7 +242,7 @@ module AuthADlw : Auth_signature.AUTH_MODULE = struct pbis_cmd ^ " " ^ List.fold_left (fun p pp -> p ^ " " ^ pp) " " pbis_args in let debug_cmd = - if String.has_substr debug_cmd "--password" then + if Astring.String.is_infix ~affix:"--password" debug_cmd then "(omitted for security)" else debug_cmd @@ -348,9 +352,9 @@ module AuthADlw : Auth_signature.AUTH_MODULE = struct if !exited_code <> 0 then ( error "execute '%s': exit_code=[%d] output=[%s]" debug_cmd !exited_code - (String.replace "\n" ";" !output) ; + (Stringext.replace '\n' ~by:";" !output) ; let split_to_words s = - String.split_f (fun c -> c = '(' || c = ')' || c = '.' || c = ' ') s + Astring.String.fields ~empty:false ~is_sep:is_word_sep s in let revlines = List.rev @@ -416,7 +420,7 @@ module AuthADlw : Auth_signature.AUTH_MODULE = struct List.filter (fun l -> String.length l > 0) (splitlines !output) in let parse_line (acc, currkey) line = - let slices = String.split ~limit:2 ':' line in + let slices = Stringext.split ~limit:2 ':' line in debug "parse %s: currkey=[%s] line=[%s]" debug_cmd currkey line ; if List.length slices > 1 then ( let key = String.trim (List.hd slices) in @@ -619,7 +623,7 @@ module AuthADlw : Auth_signature.AUTH_MODULE = struct (* first, we try to authenticated user against our external user database *) (* pbis_common will raise an Auth_failure if external authentication fails *) let domain, user = - match String.split_f (fun c -> c = '\\') username with + match Astring.String.cuts ~empty:false ~sep:"\\" username with | [domain; user] -> (domain, user) | [user] -> @@ -976,7 +980,8 @@ module AuthADlw : Auth_signature.AUTH_MODULE = struct | "" -> [] | disabled_modules_string -> - String.split_f (fun c -> c = ',') disabled_modules_string + Astring.String.cuts ~empty:false ~sep:"," + disabled_modules_string with Not_found -> [] in let disabled_module_params = @@ -1113,8 +1118,8 @@ module AuthADlw : Auth_signature.AUTH_MODULE = struct in debug "execute %s: stdout=[%s],stderr=[%s]" pbis_force_domain_leave_script - (String.replace "\n" ";" output) - (String.replace "\n" ";" stderr) + (Stringext.replace '\n' ~by:";" output) + (Stringext.replace '\n' ~by:";" stderr) with e -> debug "exception executing %s: %s" pbis_force_domain_leave_script (ExnHelper.string_of_exn e) diff --git a/ocaml/xapi/extauth_plugin_ADwinbind.ml b/ocaml/xapi/extauth_plugin_ADwinbind.ml index 837dc429ca2..86d0e8c25b2 100644 --- a/ocaml/xapi/extauth_plugin_ADwinbind.ml +++ b/ocaml/xapi/extauth_plugin_ADwinbind.ml @@ -20,7 +20,6 @@ module D = Debug.Make (struct end) open D -open Xapi_stdext_std.Xstringext open Auth_signature module Scheduler = Xapi_stdext_threads_scheduler.Scheduler diff --git a/ocaml/xapi/fileserver.ml b/ocaml/xapi/fileserver.ml index 9820a55d5ce..8c83dac57f3 100644 --- a/ocaml/xapi/fileserver.ml +++ b/ocaml/xapi/fileserver.ml @@ -16,29 +16,17 @@ *) open Http -open Xapi_stdext_std.Xstringext +module Xstringext = Xapi_stdext_std.Xstringext.String module D = Debug.Make (struct let name = "fileserver" end) open D -let escape uri = - String.escaped - ~rules: - [ - ('<', "<") - ; ('>', ">") - ; ('\'', "'") - ; ('"', """) - ; ('&', "&") - ] - uri - let missing uri = " \ 404 Not Found

Not Found

The \ requested URL " - ^ escape uri + ^ Http_svr.escape_html uri ^ " was not found on this server.


Xapi \ Server
" diff --git a/ocaml/xapi/gpg.ml b/ocaml/xapi/gpg.ml index 1dd5c8141c8..def89c7890b 100644 --- a/ocaml/xapi/gpg.ml +++ b/ocaml/xapi/gpg.ml @@ -13,7 +13,6 @@ *) (** Wrapper around gpg *) -open Xapi_stdext_std.Xstringext open Xapi_stdext_pervasives.Pervasiveext module Unixext = Xapi_stdext_unix.Unixext @@ -26,7 +25,7 @@ let gpg_binary_path = "/usr/bin/gpg" exception InvalidSignature let parse_gpg_status status_data = - let lines = String.split '\n' status_data in + let lines = String.split_on_char '\n' status_data in let status_contains substr = List.exists (fun s -> String.starts_with ~prefix:substr s) lines in @@ -42,7 +41,7 @@ let parse_gpg_status status_data = let validsigline = List.find (fun s -> String.starts_with ~prefix:validsig s) lines in - match String.split ' ' validsigline with + match String.split_on_char ' ' validsigline with | _ :: _ :: fingerprint :: _ -> Some fingerprint | _ -> diff --git a/ocaml/xapi/import.ml b/ocaml/xapi/import.ml index 04306cff5f6..c854ed1807d 100644 --- a/ocaml/xapi/import.ml +++ b/ocaml/xapi/import.ml @@ -19,7 +19,6 @@ module D = Debug.Make (struct let name = "import" end) open D module Listext = Xapi_stdext_std.Listext -module Xstringext = Xapi_stdext_std.Xstringext module Unixext = Xapi_stdext_unix.Unixext open Http open Importexport diff --git a/ocaml/xapi/map_check.ml b/ocaml/xapi/map_check.ml index 0cb2d97e37f..3737b3f00bf 100644 --- a/ocaml/xapi/map_check.ml +++ b/ocaml/xapi/map_check.ml @@ -104,7 +104,7 @@ let assert_value ~field ~key ~attr ~value = ) | EnumSet range -> (* enumset is a comma-separated string *) - let vs = Xapi_stdext_std.Xstringext.String.split ',' value in + let vs = String.split_on_char ',' value in List.fold_right (fun v acc -> match mem v range with @@ -113,7 +113,7 @@ let assert_value ~field ~key ~attr ~value = | Some v -> if acc = "" then v - else if Xapi_stdext_std.Xstringext.String.has_substr acc v then + else if Astring.String.is_infix ~affix:v acc then err value else v ^ "," ^ acc diff --git a/ocaml/xapi/nm.ml b/ocaml/xapi/nm.ml index fa86a6f08e7..4df9bf233f9 100644 --- a/ocaml/xapi/nm.ml +++ b/ocaml/xapi/nm.ml @@ -14,7 +14,7 @@ module D = Debug.Make (struct let name = "nm" end) open D -open Xapi_stdext_std.Xstringext +module Stringext = Xapi_stdext_std.Xstringext.String module Listext = Xapi_stdext_std.Listext.List open Xapi_database.Db_filter_types open Network @@ -216,7 +216,7 @@ let create_bond ~__context bond mtu persistent = List.filter_map (fun (k, v) -> if String.starts_with ~prefix:"bond-" k then - Some (String.sub_to_end k 5, v) + Some (Stringext.sub_to_end k 5, v) else None ) @@ -470,7 +470,7 @@ let determine_static_routes net_rc = if List.mem_assoc "static-routes" net_rc.API.network_other_config then try let routes = - String.split ',' + String.split_on_char ',' (List.assoc "static-routes" net_rc.API.network_other_config) in List.map diff --git a/ocaml/xapi/pciops.ml b/ocaml/xapi/pciops.ml index 2126185474e..46cfdf377cc 100644 --- a/ocaml/xapi/pciops.ml +++ b/ocaml/xapi/pciops.ml @@ -126,7 +126,8 @@ let _unhide_pci ~__context pci = Printf.sprintf "(%s)" (Db.PCI.get_pci_id ~__context ~self:pci) in let new_value = - Xapi_stdext_std.Xstringext.String.replace bdf_paren "" raw_value + Astring.String.cuts ~empty:false ~sep:bdf_paren raw_value + |> String.concat "" in let cmd = match new_value with diff --git a/ocaml/xapi/pvs_proxy_control.ml b/ocaml/xapi/pvs_proxy_control.ml index 8597166fe7b..8a64cb2c051 100644 --- a/ocaml/xapi/pvs_proxy_control.ml +++ b/ocaml/xapi/pvs_proxy_control.ml @@ -21,7 +21,9 @@ open D let proxy_port_name vif = (* Interface names in Linux are at most 15 characters. We derive a name from the MAC address to ensure uniqueness, and make it fit. *) - let mac = Xapi_stdext_std.Xstringext.String.replace ":" "" vif.API.vIF_MAC in + let mac = + Astring.String.filter (function ':' -> false | _ -> true) vif.API.vIF_MAC + in Printf.sprintf "pvs%s" mac (** [proxies] returns all currently attached proxies *) diff --git a/ocaml/xapi/rbac_audit.ml b/ocaml/xapi/rbac_audit.ml index bbc5a7a6fc9..7f86ba31030 100644 --- a/ocaml/xapi/rbac_audit.ml +++ b/ocaml/xapi/rbac_audit.ml @@ -362,8 +362,7 @@ and let has_to_audit action = let has_side_effect action = - not (Xapi_stdext_std.Xstringext.String.has_substr action ".get") - (* TODO: a bit slow? *) + not (Astring.String.is_infix ~affix:".get" action) in (!Xapi_globs.log_getter || has_side_effect action) && not @@ -454,9 +453,9 @@ let audit_line_of __context session_id allowed_denied ok_error result_error ?sexpr_of_args action permission ) in - let line = Xapi_stdext_std.Xstringext.String.replace "\n" " " _line in + let line = Xapi_stdext_std.Xstringext.String.replace '\n' ~by:" " _line in (* no \n in line *) - let line = Xapi_stdext_std.Xstringext.String.replace "\r" " " line in + let line = Xapi_stdext_std.Xstringext.String.replace '\r' ~by:" " line in (* no \r in line *) let audit_line = append_line "%s" line in (*D.debug "line=%s, audit_line=%s" line audit_line;*) @@ -471,7 +470,7 @@ let allowed_pre_fn ~__context ~action ?args () = if has_to_audit action (* for now, we only cache arg results for destroy actions *) - && Xapi_stdext_std.Xstringext.String.has_substr action ".destroy" + && Astring.String.is_infix ~affix:".destroy" action then let args' = add_dummy_args __context action args in Some (sexpr_of_parameters __context action args') diff --git a/ocaml/xapi/sm.ml b/ocaml/xapi/sm.ml index 1d198cf3f98..532f6fb44b1 100644 --- a/ocaml/xapi/sm.ml +++ b/ocaml/xapi/sm.ml @@ -15,7 +15,6 @@ * @group Storage *) -open Xapi_stdext_std.Xstringext open Smint open Printf diff --git a/ocaml/xapi/storage_mux.ml b/ocaml/xapi/storage_mux.ml index 0427f76ca54..f2091c896d0 100644 --- a/ocaml/xapi/storage_mux.ml +++ b/ocaml/xapi/storage_mux.ml @@ -97,7 +97,8 @@ module Mux = struct let m = Mutex.create () - let filename_of dp = Xapi_stdext_std.Xstringext.String.replace "/" "-" dp + let filename_of dp = + Xapi_stdext_std.Xstringext.String.replace '/' ~by:"-" dp let write dp info = let filename = filename_of dp in @@ -780,9 +781,9 @@ module Mux = struct (* Assume it has either the format: SR/VDI -- for a particular SR and VDI content_id -- for a particular content *) - let open Xapi_stdext_std.Xstringext in + let split = Xapi_stdext_std.Xstringext.String.split in with_dbg ~name:"get_by_name" ~dbg @@ fun di -> - match List.filter (fun x -> x <> "") (String.split ~limit:2 '/' name) with + match List.filter (fun x -> x <> "") (split ~limit:2 '/' name) with | [sr; name] -> let sr = Storage_interface.Sr.of_string sr in let module C = StorageAPI (Idl.Exn.GenClient (struct diff --git a/ocaml/xapi/vgpuops.ml b/ocaml/xapi/vgpuops.ml index e47b0896ab3..248ec2839a1 100644 --- a/ocaml/xapi/vgpuops.ml +++ b/ocaml/xapi/vgpuops.ml @@ -15,7 +15,6 @@ module D = Debug.Make (struct let name = "vgpuops" end) open D module Listext = Xapi_stdext_std.Listext.List -open Xapi_stdext_std.Xstringext type vgpu_t = { vgpu_ref: API.ref_VGPU diff --git a/ocaml/xapi/vhd_tool_wrapper.ml b/ocaml/xapi/vhd_tool_wrapper.ml index f3f791fe251..e8c051c0ef7 100644 --- a/ocaml/xapi/vhd_tool_wrapper.ml +++ b/ocaml/xapi/vhd_tool_wrapper.ml @@ -18,7 +18,6 @@ module D = Debug.Make (struct let name = "vhd_tool_wrapper" end) open D -open Xapi_stdext_std.Xstringext (* .vhds on XenServer are sometimes found via /dev/mapper *) let vhd_search_path = "/dev/mapper:." @@ -125,7 +124,7 @@ let find_backend_device path = let link = Unix.readlink (Printf.sprintf "/sys/dev/block/%d:%d/device" major minor) in - match List.rev (String.split '/' link) with + match List.rev (String.split_on_char '/' link) with | id :: "xen" :: "devices" :: _ when Astring.String.is_prefix ~affix:"vbd-" id -> let id = int_of_string (String.sub id 4 (String.length id - 4)) in @@ -135,7 +134,7 @@ let find_backend_device path = xs.Xs.read (Printf.sprintf "device/vbd/%d/backend" id) in let params = xs.Xs.read (Printf.sprintf "%s/params" backend) in - match String.split '/' backend with + match String.split_on_char '/' backend with | "local" :: "domain" :: bedomid :: _ -> if not (self = bedomid) then Helpers.internal_error diff --git a/ocaml/xapi/wlb_reports.ml b/ocaml/xapi/wlb_reports.ml index e466bf959f5..8de0e80b298 100644 --- a/ocaml/xapi/wlb_reports.ml +++ b/ocaml/xapi/wlb_reports.ml @@ -92,7 +92,6 @@ open Printf open Http -open Xapi_stdext_std.Xstringext module D = Debug.Make (struct let name = "wlb_reports" end) diff --git a/ocaml/xapi/workload_balancing.ml b/ocaml/xapi/workload_balancing.ml index 7108032dbf7..136aa2c8985 100644 --- a/ocaml/xapi/workload_balancing.ml +++ b/ocaml/xapi/workload_balancing.ml @@ -16,7 +16,6 @@ *) open Printf -open Xapi_stdext_std.Xstringext module D = Debug.Make (struct let name = "workload_balancing" end) @@ -75,24 +74,12 @@ let raise_internal_error args = raise (Api_errors.Server_error (Api_errors.wlb_internal_error, args)) let split_host_port url = - try - if url.[0] = '[' then ( - (* IPv6 *) - let host_end = String.rindex url ']' in - if url.[host_end + 1] <> ':' then - raise_url_invalid url ; - let host = String.sub url 1 (host_end - 1) in - let port = - String.sub url (host_end + 2) (String.length url - host_end - 2) - in - (host, int_of_string port) - ) else - match String.split_f (fun a -> a = ':') url with - | [host; port] -> - (host, int_of_string port) - | _ -> - raise_url_invalid url - with _ -> raise_url_invalid url + let uri = Uri.of_string ("//" ^ url) in + match (Uri.host uri, Uri.port uri) with + | None, _ | _, None -> + raise_url_invalid url + | Some host, Some port -> + (host, port) let wlb_host_port ~__context = let pool = Helpers.get_pool ~__context in diff --git a/ocaml/xapi/xapi_dr_task.ml b/ocaml/xapi/xapi_dr_task.ml index de7d15e0523..56626ea1368 100644 --- a/ocaml/xapi/xapi_dr_task.ml +++ b/ocaml/xapi/xapi_dr_task.ml @@ -13,7 +13,6 @@ *) open Client -open Xapi_stdext_std.Xstringext module D = Debug.Make (struct let name = "xapi_dr_task" end) diff --git a/ocaml/xapi/xapi_globs.ml b/ocaml/xapi/xapi_globs.ml index 161273c83f9..8a062edbf29 100644 --- a/ocaml/xapi/xapi_globs.ml +++ b/ocaml/xapi/xapi_globs.ml @@ -14,8 +14,6 @@ (** A central location for settings related to xapi *) -module String_plain = String (* For when we don't want the Xstringext version *) -open Xapi_stdext_std.Xstringext module StringSet = Set.Make (String) module D = Debug.Make (struct let name = "xapi_globs" end) @@ -1366,12 +1364,12 @@ let citrix_patch_key = let trusted_patch_key = ref citrix_patch_key +let fields_of = Astring.(String.fields ~empty:false ~is_sep:Char.Ascii.is_white) + let gen_list_option name desc of_string string_of opt = let parse s = opt := [] ; - try - String.split_f String.isspace s - |> List.iter (fun x -> opt := of_string x :: !opt) + try fields_of s |> List.iter (fun x -> opt := of_string x :: !opt) with e -> D.error "Unable to parse %s=%s (expected space-separated list) error: %s" name s (Printexc.to_string e) @@ -1466,7 +1464,7 @@ let other_options = (fun s -> s) disable_dbsync_for ; ( "xenopsd-queues" - , Arg.String (fun x -> xenopsd_queues := String.split ',' x) + , Arg.String (fun x -> xenopsd_queues := String.split_on_char ',' x) , (fun () -> String.concat "," !xenopsd_queues) , "list of xenopsd instances to manage" ) @@ -1553,7 +1551,8 @@ let other_options = ; ( "nvidia_multi_vgpu_enabled_driver_versions" , Arg.String (fun x -> - nvidia_multi_vgpu_enabled_driver_versions := String.split ',' x + nvidia_multi_vgpu_enabled_driver_versions := + String.split_on_char ',' x ) , (fun () -> String.concat "," !nvidia_multi_vgpu_enabled_driver_versions) , "list of nvidia host driver versions with multiple vGPU supported.\n\ diff --git a/ocaml/xapi/xapi_host_crashdump.ml b/ocaml/xapi/xapi_host_crashdump.ml index b7e9eedd74e..f9c66de62c8 100644 --- a/ocaml/xapi/xapi_host_crashdump.ml +++ b/ocaml/xapi/xapi_host_crashdump.ml @@ -16,7 +16,6 @@ *) module Listext = Xapi_stdext_std.Listext -module Xstringext = Xapi_stdext_std.Xstringext module Date = Clock.Date open Xapi_stdext_pervasives.Pervasiveext open Xapi_support @@ -50,6 +49,8 @@ let delete_crashdump_dir filename = (ExnHelper.string_of_exn e) ; raise e +let fields_of = Astring.(String.fields ~empty:false ~is_sep:Char.Ascii.is_white) + (* Called once on host boot to resync the crash directory with the database *) let resynchronise ~__context ~host = debug "Xapi_host_crashdump.resynchronise" ; @@ -103,9 +104,7 @@ let resynchronise ~__context ~host = debug "Adding record corresponding to new crashdump %s" filename ; let cmd = Printf.sprintf "%s --bytes -s %s/%s" du crash_dir filename in let size = - match - Xstringext.String.(split_f isspace (Helpers.get_process_output cmd)) - with + match fields_of (Helpers.get_process_output cmd) with | size :: _ -> Int64.of_string size | _ -> diff --git a/ocaml/xapi/xapi_network.ml b/ocaml/xapi/xapi_network.ml index 73a59fd698c..dd937ad5784 100644 --- a/ocaml/xapi/xapi_network.ml +++ b/ocaml/xapi/xapi_network.ml @@ -14,7 +14,6 @@ let with_lock = Xapi_stdext_threads.Threadext.Mutex.execute open Client -open Xapi_stdext_std.Xstringext module D = Debug.Make (struct let name = "xapi_network" end) diff --git a/ocaml/xapi/xapi_pif.ml b/ocaml/xapi/xapi_pif.ml index 881c51091fb..ccebf243816 100644 --- a/ocaml/xapi/xapi_pif.ml +++ b/ocaml/xapi/xapi_pif.ml @@ -19,7 +19,6 @@ module L = Debug.Make (struct let name = "license" end) open Xapi_database.Db_filter_types module Listext = Xapi_stdext_std.Listext.List -open Xapi_stdext_std.Xstringext module Date = Clock.Date open Network @@ -216,7 +215,9 @@ let refresh_all ~__context ~host = pifs let read_bridges_from_inventory () = - try String.split ' ' (Xapi_inventory.lookup Xapi_inventory._current_interfaces) + try + String.split_on_char ' ' + (Xapi_inventory.lookup Xapi_inventory._current_interfaces) with _ -> [] (* Ensure the PIF is not a bond slave. *) @@ -707,6 +708,8 @@ let forget ~__context ~self = let scan_m = Mutex.create () +let fields_of = Astring.(String.fields ~empty:false ~is_sep:Char.Ascii.is_white) + let scan ~__context ~host = let dbg = Context.string_of_task __context in refresh_all ~__context ~host ; @@ -716,15 +719,15 @@ let scan ~__context ~host = let output, _ = Forkhelpers.execute_command_get_output !Xapi_globs.non_managed_pifs [] in - let dsplit = String.split '\n' output in + let dsplit = String.split_on_char '\n' output in match dsplit with | [] | [""] | "" :: "" :: _ -> debug "No boot from SAN interface found" ; ([], []) | m :: u :: _ -> - (String.split_f String.isspace m, String.split_f String.isspace u) + (fields_of m, fields_of u) | m :: _ -> - (String.split_f String.isspace m, []) + (fields_of m, []) with e -> warn "Error when executing script %s: %s; ignoring" !Xapi_globs.non_managed_pifs diff --git a/ocaml/xapi/xapi_pool.ml b/ocaml/xapi/xapi_pool.ml index 752d822135f..89e656ec8e2 100644 --- a/ocaml/xapi/xapi_pool.ml +++ b/ocaml/xapi/xapi_pool.ml @@ -16,7 +16,6 @@ open Client module Date = Clock.Date module Listext = Xapi_stdext_std.Listext module Unixext = Xapi_stdext_unix.Unixext -module Xstringext = Xapi_stdext_std.Xstringext module Pkgs = (val Pkg_mgr.get_pkg_mgr) diff --git a/ocaml/xapi/xapi_pool_update.ml b/ocaml/xapi/xapi_pool_update.ml index 6aa1ea0fd71..a0b0534628a 100644 --- a/ocaml/xapi/xapi_pool_update.ml +++ b/ocaml/xapi/xapi_pool_update.ml @@ -12,7 +12,7 @@ * GNU Lesser General Public License for more details. *) -open Xapi_stdext_std.Xstringext +module Stringext = Xapi_stdext_std.Xstringext.String module Unixext = Xapi_stdext_unix.Unixext open Http open Helpers @@ -376,7 +376,7 @@ let parse_update_info xml = | "" -> [] | s -> - List.map guidance_from_string (String.split ',' s) + List.map guidance_from_string (String.split_on_char ',' s) with _ -> [] in let enforce_homogeneity = @@ -770,9 +770,10 @@ let resync_host ~__context ~host = let path_and_host_from_uri uri = (* remove any dodgy use of "." or ".." NB we don't prevent the use of symlinks *) let host_and_path = - String.sub_to_end uri (String.length Constants.get_pool_update_download_uri) + Stringext.sub_to_end uri + (String.length Constants.get_pool_update_download_uri) in - match String.split ~limit:2 '/' host_and_path with + match Stringext.split ~limit:2 '/' host_and_path with | [host; untrusted_path] -> let resolved_path = untrusted_path diff --git a/ocaml/xapi/xapi_secret.ml b/ocaml/xapi/xapi_secret.ml index 57492840ead..9ca6eb88276 100644 --- a/ocaml/xapi/xapi_secret.ml +++ b/ocaml/xapi/xapi_secret.ml @@ -15,8 +15,6 @@ * @group XenAPI functions *) -open Xapi_stdext_std.Xstringext - module D = Debug.Make (struct let name = "xapi_secret" end) open D diff --git a/ocaml/xapi/xapi_vbd_helpers.ml b/ocaml/xapi/xapi_vbd_helpers.ml index 07d6b012da2..7fe8f32aa50 100644 --- a/ocaml/xapi/xapi_vbd_helpers.ml +++ b/ocaml/xapi/xapi_vbd_helpers.ml @@ -15,7 +15,6 @@ * @group Storage *) -open Xapi_stdext_std.Xstringext module Listext = Xapi_stdext_std.Listext module Date = Clock.Date diff --git a/ocaml/xapi/xapi_vif_helpers.ml b/ocaml/xapi/xapi_vif_helpers.ml index 37de1b77770..9bc87f3a553 100644 --- a/ocaml/xapi/xapi_vif_helpers.ml +++ b/ocaml/xapi/xapi_vif_helpers.ml @@ -12,8 +12,6 @@ * GNU Lesser General Public License for more details. *) -open Xapi_stdext_std.Xstringext - module D = Debug.Make (struct let name = "xapi_vif_helpers" end) open D diff --git a/ocaml/xapi/xapi_vusb_helpers.ml b/ocaml/xapi/xapi_vusb_helpers.ml index 19298735a06..0cf59fa5167 100644 --- a/ocaml/xapi/xapi_vusb_helpers.ml +++ b/ocaml/xapi/xapi_vusb_helpers.ml @@ -12,8 +12,6 @@ * GNU Lesser General Public License for more details. *) -open Xapi_stdext_std.Xstringext - module D = Debug.Make (struct let name = "xapi_vusb_helpers" end) (**************************************************************************************) diff --git a/ocaml/xapi/xapi_xenops.ml b/ocaml/xapi/xapi_xenops.ml index 0ea29ea4cf7..a39a9983c86 100644 --- a/ocaml/xapi/xapi_xenops.ml +++ b/ocaml/xapi/xapi_xenops.ml @@ -17,9 +17,9 @@ module D = Debug.Make (struct let name = "xenops" end) open D module StringSet = Set.Make (String) open Network -open Xapi_stdext_std.Xstringext module Date = Clock.Date module Listext = Xapi_stdext_std.Listext.List +module Stringext = Xapi_stdext_std.Xstringext.String let with_lock = Xapi_stdext_threads.Threadext.Mutex.execute @@ -129,7 +129,7 @@ let disk_of_vdi ~__context ~self = let vdi_of_disk ~__context x = let@ __context = Context.with_tracing ~__context __FUNCTION__ in - match String.split ~limit:2 '/' x with + match Stringext.split ~limit:2 '/' x with | [sr_uuid; location] -> ( let open Xapi_database.Db_filter_types in let sr = Db.SR.get_by_uuid ~__context ~uuid:sr_uuid in @@ -1182,8 +1182,8 @@ module MD = struct let affinity = try List.map - (fun x -> List.map int_of_string (String.split ',' x)) - (String.split ';' (List.assoc "mask" vm.API.vM_VCPUs_params)) + (fun x -> List.map int_of_string (String.split_on_char ',' x)) + (String.split_on_char ';' (List.assoc "mask" vm.API.vM_VCPUs_params)) with _ -> [] in let localhost = Helpers.get_localhost ~__context in @@ -1193,7 +1193,9 @@ module MD = struct let host_cpu_mask = try List.map int_of_string - (String.split ',' (List.assoc "mask" host_guest_VCPUs_params)) + (String.split_on_char ',' + (List.assoc "mask" host_guest_VCPUs_params) + ) with _ -> [] in let affinity = @@ -1981,7 +1983,9 @@ let update_vm_internal ~__context ~id ~self ~previous ~info ~localhost = String.sub path (String.length dir) (String.length path - String.length dir) in - match List.filter (fun x -> x <> "") (String.split '/' rest) with + match + List.filter (fun x -> x <> "") (String.split_on_char '/' rest) + with | x :: _ -> Some x | _ -> diff --git a/ocaml/xapi/xha_interface.ml b/ocaml/xapi/xha_interface.ml index 82ac381519d..dee90350575 100644 --- a/ocaml/xapi/xha_interface.ml +++ b/ocaml/xapi/xha_interface.ml @@ -12,7 +12,6 @@ * GNU Lesser General Public License for more details. *) open API -open Xapi_stdext_std.Xstringext let hashtbl_of_list xs = let tbl = Hashtbl.create (List.length xs) in @@ -350,7 +349,10 @@ module LiveSetInformation = struct | Some u -> u in - let set f x = List.map f (String.split_f String.isspace x) in + let fields_of = + Astring.(String.fields ~empty:false ~is_sep:Char.Ascii.is_white) + in + let set f x = List.map f (fields_of x) in Some { id= uuid (find "HostID") diff --git a/ocaml/xcp-rrdd/bin/rrdp-iostat/rrdp_iostat.ml b/ocaml/xcp-rrdd/bin/rrdp-iostat/rrdp_iostat.ml index 6141090eae7..cad87fc6614 100644 --- a/ocaml/xcp-rrdd/bin/rrdp-iostat/rrdp_iostat.ml +++ b/ocaml/xcp-rrdd/bin/rrdp-iostat/rrdp_iostat.ml @@ -437,7 +437,7 @@ let exec_tap_ctl_list () : ((string * string) * int) list = let minor_of_tapdev_unsafe tapdev = int_of_string (Unixext.file_lines_fold - (fun acc l -> acc ^ List.nth (Xstringext.String.split ':' l) 1) + (fun acc l -> acc ^ List.nth (String.split_on_char ':' l) 1) "" ("/sys/block/" ^ tapdev ^ "/dev") ) diff --git a/ocaml/xcp-rrdd/bin/rrdp-squeezed/rrdp_squeezed.ml b/ocaml/xcp-rrdd/bin/rrdp-squeezed/rrdp_squeezed.ml index df49dca259f..55a190b8988 100644 --- a/ocaml/xcp-rrdd/bin/rrdp-squeezed/rrdp_squeezed.ml +++ b/ocaml/xcp-rrdd/bin/rrdp-squeezed/rrdp_squeezed.ml @@ -12,7 +12,6 @@ * GNU Lesser General Public License for more details. *) -open Xapi_stdext_std open Rrdd_plugin module Process = Process (struct let name = "xcp-rrdd-squeezed" end) @@ -81,7 +80,7 @@ module MemoryActions = struct path domid ; current_memory_values := IntMap.remove domid !current_memory_values in - match List.filter (fun x -> x <> "") (Xstringext.String.split '/' path) with + match List.filter (fun x -> x <> "") (String.split_on_char '/' path) with | ["local"; "domain"; domid; "memory"; "dynamic-max"] -> read_new_value domid current_dynamic_max_values | ["local"; "domain"; domid; "memory"; "dynamic-min"] -> diff --git a/ocaml/xe-cli/dune b/ocaml/xe-cli/dune index b61ec3cde63..3aed1017987 100644 --- a/ocaml/xe-cli/dune +++ b/ocaml/xe-cli/dune @@ -17,7 +17,6 @@ xapi-backtrace xapi-cli-protocol xapi-stdext-pervasives - xapi-stdext-std xapi-stdext-unix ) ) diff --git a/ocaml/xe-cli/newcli.ml b/ocaml/xe-cli/newcli.ml index 60ecce2a47d..0b18d57dd18 100644 --- a/ocaml/xe-cli/newcli.ml +++ b/ocaml/xe-cli/newcli.ml @@ -13,7 +13,6 @@ *) (* New cli talking to the in-server cli interface *) -open Xapi_stdext_std.Xstringext open Xapi_stdext_pervasives open Cli_protocol @@ -306,7 +305,7 @@ let parse_args = || (extra_args.[!i] = ',' && extra_args.[!i - 1] <> '\\') then ( let seg = String.sub extra_args !pos (!i - !pos) in - l := String.filter_chars seg (( <> ) '\\') :: !l ; + l := Astring.String.filter (( <> ) '\\') seg :: !l ; incr i ; pos := !i ) else @@ -389,7 +388,7 @@ let with_open_channels f = match result with Ok r -> r | Error e -> raise e let http_response_code x = - match String.split ' ' x with + match String.split_on_char ' ' x with | _ :: code :: _ -> int_of_string code | _ ->