From c1b52315c4bfc6dfc1b5d515b2f5d8474c192d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= Date: Fri, 19 Apr 2024 17:33:27 +0100 Subject: [PATCH] IH-553: Sexpr.escape should be a noop when nothing to escape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Optimistically check for the presence of escape characters before escaping. This avoids rebuilding the string when escapable characters are not present (the common case). Signed-off-by: Edwin Török --- ocaml/libs/sexpr/sExpr.ml | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/ocaml/libs/sexpr/sExpr.ml b/ocaml/libs/sexpr/sExpr.ml index f4630981248..1a5eb9cf907 100644 --- a/ocaml/libs/sexpr/sExpr.ml +++ b/ocaml/libs/sexpr/sExpr.ml @@ -27,6 +27,8 @@ let unescape_buf buf s = if Astring.String.fold_left aux false s then Buffer.add_char buf '\\' +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. @@ -36,21 +38,24 @@ let unescape_buf buf s = * that have guaranteed invariants and optimised performances *) let escape s = let open Astring in - let escaped = Buffer.create (String.length s + 10) in - String.iter - (fun c -> - match c with - | '\\' -> - Buffer.add_string escaped "\\\\" - | '"' -> - Buffer.add_string escaped "\\\"" - | '\'' -> - Buffer.add_string escaped "\\\'" - | _ -> - Buffer.add_char escaped c - ) - s ; - Buffer.contents escaped + if String.exists is_escape_char s then ( + let escaped = Buffer.create (String.length s + 10) in + String.iter + (fun c -> + match c with + | '\\' -> + Buffer.add_string escaped "\\\\" + | '"' -> + Buffer.add_string escaped "\\\"" + | '\'' -> + Buffer.add_string escaped "\\\'" + | _ -> + Buffer.add_char escaped c + ) + s ; + Buffer.contents escaped + ) else + s let unescape s = let buf = Buffer.create (String.length s) in