Pure OCaml Yaml 1.2 reader and writer using Bytesrw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6(** YAML scalar quoting detection *) 7 8(** Check if a string value needs quoting in YAML output. 9 Returns true if the string: 10 - Is empty 11 - Starts with an indicator character 12 - Is a reserved word (null, true, false, yes, no, etc.) 13 - Contains characters that would be ambiguous 14 - Looks like a number *) 15let needs_quoting s = 16 if String.length s = 0 then true 17 else 18 let first = s.[0] in 19 (* Check first character for indicators *) 20 if first = '-' || first = '?' || first = ':' || first = ',' || 21 first = '[' || first = ']' || first = '{' || first = '}' || 22 first = '#' || first = '&' || first = '*' || first = '!' || 23 first = '|' || first = '>' || first = '\'' || first = '"' || 24 first = '%' || first = '@' || first = '`' || first = ' ' then 25 true 26 else 27 (* Check for reserved/special values *) 28 let lower = String.lowercase_ascii s in 29 if lower = "null" || lower = "true" || lower = "false" || 30 lower = "yes" || lower = "no" || lower = "on" || lower = "off" || 31 lower = "~" || lower = ".inf" || lower = "-.inf" || lower = ".nan" then 32 true 33 else 34 (* Check for problematic characters *) 35 try 36 String.iter (fun c -> 37 if c = ':' || c = '#' || c = '\n' || c = '\r' then 38 raise Exit 39 ) s; 40 (* Check if it looks like a number *) 41 (try ignore (Float.of_string s); true with _ -> false) 42 with Exit -> true 43 44(** Check if a string requires double quotes (vs single quotes). 45 Returns true if the string contains characters that need escape sequences. *) 46let needs_double_quotes s = 47 try 48 String.iter (fun c -> 49 if c = '\n' || c = '\r' || c = '\t' || c = '\\' || 50 c < ' ' || c = '"' then 51 raise Exit 52 ) s; 53 false 54 with Exit -> true 55 56(** Choose the appropriate quoting style for a string value *) 57let choose_style s = 58 match (needs_double_quotes s, needs_quoting s) with 59 | (true, _) -> `Double_quoted 60 | (_, true) -> `Single_quoted 61 | _ -> `Plain 62