Pure OCaml Yaml 1.2 reader and writer using Bytesrw
at main 2.4 kB view raw
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. Returns true if the 9 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 21 first = '-' || first = '?' || first = ':' || first = ',' || first = '[' 22 || first = ']' || first = '{' || first = '}' || first = '#' || first = '&' 23 || first = '*' || first = '!' || first = '|' || first = '>' 24 || first = '\'' || first = '"' || first = '%' || first = '@' 25 || first = '`' || first = ' ' 26 then true 27 else 28 (* Check for reserved/special values *) 29 let lower = String.lowercase_ascii s in 30 if 31 lower = "null" || lower = "true" || lower = "false" || lower = "yes" 32 || lower = "no" || lower = "on" || lower = "off" || lower = "~" 33 || lower = ".inf" || lower = "-.inf" || lower = ".nan" 34 then true 35 else 36 (* Check for problematic characters *) 37 try 38 String.iter 39 (fun c -> 40 if c = ':' || c = '#' || c = '\n' || c = '\r' then raise Exit) 41 s; 42 (* Check if it looks like a number *) 43 try 44 ignore (Float.of_string s); 45 true 46 with _ -> false 47 with Exit -> true 48 49(** Check if a string requires double quotes (vs single quotes). Returns true if 50 the string contains characters that need escape sequences. *) 51let needs_double_quotes s = 52 try 53 String.iter 54 (fun c -> 55 if c = '\n' || c = '\r' || c = '\t' || c = '\\' || c < ' ' || c = '"' 56 then raise Exit) 57 s; 58 false 59 with Exit -> true 60 61(** Choose the appropriate quoting style for a string value *) 62let choose_style s = 63 match (needs_double_quotes s, needs_quoting s) with 64 | true, _ -> `Double_quoted 65 | _, true -> `Single_quoted 66 | _ -> `Plain