Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
printer.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
open Types let maybe_escape_char formatter ch = match ch with | '"' -> Format.pp_print_string formatter "\\\"" | '\\' -> Format.pp_print_string formatter "\\\\" | '\n' -> Format.pp_print_string formatter "\\n" | '\t' -> Format.pp_print_string formatter "\\t" | _ -> let code = Char.code ch in if code <= 31 then Format.fprintf formatter "\\u%04x" code else Format.pp_print_char formatter ch let print_bool formatter value = Format.pp_print_bool formatter value let print_int formatter value = Format.pp_print_int formatter value let print_float formatter value = let fractional = abs_float (value -. floor value) in (* Even 1.'s fractional value is not equal to 0. *) if fractional <= epsilon_float then Format.fprintf formatter "%.1f" value else Format.pp_print_float formatter value let print_string formatter value = let has_newline = ref false in let has_quote = ref false in let has_doublequote = ref false in String.iter (function | '\n' -> has_newline := true | '\'' -> has_quote := true | '"' -> has_doublequote := true | _ -> () ) value; match (!has_newline, !has_doublequote, !has_quote) with | true, false, _ -> Format.pp_print_string formatter {|"""|}; String.iter (function | '\n' -> Format.pp_print_newline formatter () | c -> maybe_escape_char formatter c ) value; Format.pp_print_string formatter {|"""|} | true, true, false -> Format.pp_print_string formatter "'''\n"; Format.pp_print_string formatter value; Format.pp_print_string formatter "'''" | _ -> Format.pp_print_char formatter '"'; String.iter (maybe_escape_char formatter) value; Format.pp_print_char formatter '"' let print_date fmt d = ISO8601.Permissive.pp_datetimezone fmt (d, 0.) (* This function is a shim for [Format.pp_print_list] from ocaml 4.02 *) let pp_print_list ~pp_sep print_item_func formatter values = match values with | [] -> () | [ e ] -> print_item_func formatter e | e :: l -> print_item_func formatter e; List.iter (fun v -> pp_sep formatter (); print_item_func formatter v ) l let is_table _ = function | TTable _ -> true | TArray (NodeTable _) -> true | _ -> false let is_array_of_table _ = function TArray (NodeTable _) -> true | _ -> false let rec print_array formatter toml_array sections = let print_list values ~f:print_item_func = let pp_sep formatter () = Format.pp_print_string formatter ", " in Format.pp_print_char formatter '['; pp_print_list ~pp_sep print_item_func formatter values; Format.pp_print_char formatter ']' in match toml_array with | NodeBool values -> print_list values ~f:print_bool | NodeInt values -> print_list values ~f:print_int | NodeFloat values -> print_list values ~f:print_float | NodeString values -> print_list values ~f:print_string | NodeDate values -> print_list values ~f:print_date | NodeArray values -> print_list values ~f:(fun formatter arr -> print_array formatter arr sections ) | NodeTable values -> List.iter (fun tbl -> (* * Don't print the intermediate sections, if all values are arrays of tables, * print [[x.y.z]] as appropriate instead of [[x]][[y]][[z]] *) if not (Types.Table.for_all is_array_of_table tbl) then Format.fprintf formatter "[[%s]]\n" (sections |> List.map Types.Table.Key.to_string |> String.concat "."); print_table formatter tbl sections ) values | NodeEmpty -> Format.pp_print_string formatter "[]" and print_table formatter toml_table sections = (* * We need to print non-table values first, otherwise we risk including * top-level values in a section by accident *) let table_with_table_values, table_with_non_table_values = Types.Table.partition is_table toml_table in let print_key_value key value = print_value_with_key formatter key value sections in (* iter() guarantees that keys are returned in ascending order *) Types.Table.iter print_key_value table_with_non_table_values; Types.Table.iter print_key_value table_with_table_values and print_value formatter toml_value sections = match toml_value with | TBool value -> print_bool formatter value | TInt value -> print_int formatter value | TFloat value -> print_float formatter value | TString value -> print_string formatter value | TDate value -> print_date formatter value | TArray value -> print_array formatter value sections | TTable value -> print_table formatter value sections and print_value_with_key formatter key toml_value sections = let sections', add_linebreak = match toml_value with | TTable value -> let sections_with_key = sections @ [ key ] in (* * Don't print the intermediate sections, if all values are tables, * print [x.y.z] as appropriate instead of [x][y][z] *) if not (Types.Table.for_all is_table value) then Format.fprintf formatter "[%s]\n" ( sections_with_key |> List.map Types.Table.Key.to_string |> String.concat "." ); (sections_with_key, false) | TArray (NodeTable _tables) -> let sections_with_key = sections @ [ key ] in (sections_with_key, false) | _ -> Format.fprintf formatter "%s = " (Types.Table.Key.to_string key); (sections, true) in print_value formatter toml_value sections'; if add_linebreak then Format.pp_print_char formatter '\n' let value formatter toml_value = print_value formatter toml_value []; Format.pp_print_flush formatter () let array formatter toml_array = match toml_array with | NodeTable _t -> (* We need the parent section for printing an array of table correctly, otheriwise the header contains [[]] *) invalid_arg "Cannot format array of tables, use Toml.Printer.table" | _ -> print_array formatter toml_array []; Format.pp_print_flush formatter () let table formatter toml_table = print_table formatter toml_table []; Format.pp_print_flush formatter () let mk_printer fn x = let b = Buffer.create 100 in let fmt = Format.formatter_of_buffer b in fn fmt x; Buffer.contents b let string_of_table = mk_printer table let string_of_value = mk_printer value let string_of_array = mk_printer array