GPS Exchange Format library/CLI in OCaml
at main 2.3 kB view raw
1(** GPX Eio I/O operations *) 2 3(** Read GPX from file path *) 4let read_file ?(validate=false) ~fs path = 5 let content = Eio.Path.load Eio.Path.(fs / path) in 6 match Gpx.parse_string ~validate content with 7 | Ok gpx -> gpx 8 | Error err -> raise (Gpx.Gpx_error err) 9 10(** Write GPX to file path *) 11let write_file ?(validate=false) ~fs path gpx = 12 match Gpx.write_string ~validate gpx with 13 | Ok xml_string -> 14 Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / path) xml_string 15 | Error err -> raise (Gpx.Gpx_error err) 16 17(** Read GPX from Eio source *) 18let read_source ?(validate=false) source = 19 let content = Eio.Flow.read_all source in 20 match Gpx.parse_string ~validate content with 21 | Ok gpx -> gpx 22 | Error err -> raise (Gpx.Gpx_error err) 23 24(** Write GPX to Eio sink *) 25let write_sink ?(validate=false) sink gpx = 26 match Gpx.write_string ~validate gpx with 27 | Ok xml_string -> 28 Eio.Flow.copy_string xml_string sink 29 | Error err -> raise (Gpx.Gpx_error err) 30 31(** Check if file exists *) 32let file_exists ~fs path = 33 try 34 let _stat = Eio.Path.stat ~follow:true Eio.Path.(fs / path) in 35 true 36 with 37 | _ -> false 38 39(** Get file size *) 40let file_size ~fs path = 41 try 42 let stat = Eio.Path.stat ~follow:true Eio.Path.(fs / path) in 43 Optint.Int63.to_int stat.size 44 with 45 | exn -> raise (Gpx.Gpx_error (Gpx.Error.io_error (Printexc.to_string exn))) 46 47(** Create backup of existing file *) 48let create_backup ~fs path = 49 if file_exists ~fs path then 50 let backup_path = path ^ ".backup" in 51 let content = Eio.Path.load Eio.Path.(fs / path) in 52 Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / backup_path) content; 53 backup_path 54 else 55 "" 56 57(** Write GPX to file with automatic backup *) 58let write_file_with_backup ?(validate=false) ~fs path gpx = 59 let backup_path = create_backup ~fs path in 60 try 61 write_file ~validate ~fs path gpx; 62 backup_path 63 with 64 | Gpx.Gpx_error _ as err -> 65 (* Try to restore backup if write failed *) 66 if backup_path <> "" && file_exists ~fs backup_path then ( 67 try 68 let backup_content = Eio.Path.load Eio.Path.(fs / backup_path) in 69 Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / path) backup_content 70 with _ -> () (* Ignore restore errors *) 71 ); 72 raise err