package mlgpx

  1. Overview
  2. Docs

Source file gpx_io.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
(** GPX Eio I/O operations *)

(** Read GPX from file path *)
let read_file ?(validate=false) ~fs path =
  let content = Eio.Path.load Eio.Path.(fs / path) in
  match Gpx.parse_string ~validate content with
  | Ok gpx -> gpx
  | Error err -> raise (Gpx.Gpx_error err)

(** Write GPX to file path *)
let write_file ?(validate=false) ~fs path gpx =
  match Gpx.write_string ~validate gpx with
  | Ok xml_string -> 
    Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / path) xml_string
  | Error err -> raise (Gpx.Gpx_error err)

(** Read GPX from Eio source *)
let read_source ?(validate=false) source =
  let content = Eio.Flow.read_all source in
  match Gpx.parse_string ~validate content with
  | Ok gpx -> gpx
  | Error err -> raise (Gpx.Gpx_error err)

(** Write GPX to Eio sink *)
let write_sink ?(validate=false) sink gpx =
  match Gpx.write_string ~validate gpx with
  | Ok xml_string -> 
    Eio.Flow.copy_string xml_string sink
  | Error err -> raise (Gpx.Gpx_error err)

(** Check if file exists *)
let file_exists ~fs path =
  try
    let _stat = Eio.Path.stat ~follow:true Eio.Path.(fs / path) in
    true
  with
  | _ -> false

(** Get file size *)
let file_size ~fs path =
  try
    let stat = Eio.Path.stat ~follow:true Eio.Path.(fs / path) in
    Optint.Int63.to_int stat.size
  with
  | exn -> raise (Gpx.Gpx_error (Gpx.Error.io_error (Printexc.to_string exn)))

(** Create backup of existing file *)
let create_backup ~fs path =
  if file_exists ~fs path then
    let backup_path = path ^ ".backup" in
    let content = Eio.Path.load Eio.Path.(fs / path) in
    Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / backup_path) content;
    backup_path
  else
    ""

(** Write GPX to file with automatic backup *)
let write_file_with_backup ?(validate=false) ~fs path gpx =
  let backup_path = create_backup ~fs path in
  try
    write_file ~validate ~fs path gpx;
    backup_path
  with
  | Gpx.Gpx_error _ as err ->
    (* Try to restore backup if write failed *)
    if backup_path <> "" && file_exists ~fs backup_path then (
      try
        let backup_content = Eio.Path.load Eio.Path.(fs / backup_path) in
        Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / path) backup_content
      with _ -> () (* Ignore restore errors *)
    );
    raise err
OCaml

Innovation. Community. Security.