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 ->
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 _ -> ()
);
raise err