+2
-4
README.md
+2
-4
README.md
···
14
14
dune build @install
15
15
dune install
16
16
17
-
# Or use opam (when published)
17
+
# Or use opam
18
18
opam install mlgpx
19
19
```
20
20
···
63
63
The library is split into four main components:
64
64
65
65
### Core Library (`gpx`)
66
-
- **Portable**: No Unix dependencies, works with js_of_ocaml
66
+
- **Portable**: No Unix dependencies, works with `js_of_ocaml`
67
67
- **Streaming**: Uses xmlm for memory-efficient XML processing
68
68
- **Type-safe**: Strong typing with validation for coordinates and GPS data
69
69
- **Pure functional**: No side effects in the core parsing/writing logic
···
283
283
284
284
let () = create_simple_gpx ()
285
285
```
286
-
287
-
+2
-2
lib/gpx/gpx.mli
+2
-2
lib/gpx/gpx.mli
···
499
499
This core module provides the foundation. For complete applications, consider:
500
500
501
501
- {!Gpx_unix}: File I/O operations using standard Unix libraries
502
-
- [Gpx_eio]: Concurrent file I/O using the Eio effects library
502
+
- {!Gpx_eio}: Concurrent file I/O using the Eio effects library
503
503
- {{:https://erratique.ch/software/xmlm}Xmlm}: Underlying XML processing library
504
504
- {{:https://erratique.ch/software/ptime}Ptime}: Time representation used for timestamps
505
505
···
508
508
- {{:https://www.topografix.com/gpx.asp}Official GPX specification}
509
509
- {{:https://www.topografix.com/GPX/1/1/gpx.xsd}GPX 1.1 XML Schema}
510
510
- {{:https://en.wikipedia.org/wiki/GPS_Exchange_Format}GPX Format on Wikipedia}
511
-
- {{:https://en.wikipedia.org/wiki/World_Geodetic_System}WGS84 Coordinate System} *)
511
+
- {{:https://en.wikipedia.org/wiki/World_Geodetic_System}WGS84 Coordinate System} *)
+6
-14
lib/gpx_eio/gpx_eio.ml
+6
-14
lib/gpx_eio/gpx_eio.ml
···
1
-
(** High-level Eio API for GPX operations *)
1
+
(** Eio API for GPX operations *)
2
2
3
-
(* I/O module *)
4
3
module IO = Gpx_io
5
-
6
-
(** Convenience functions for common operations *)
7
4
8
5
(** Read and parse GPX file *)
9
6
let read ?(validate=false) ~fs path = IO.read_file ~validate ~fs path
···
20
17
(** Write GPX to Eio sink *)
21
18
let to_sink ?(validate=false) sink gpx = IO.write_sink ~validate sink gpx
22
19
23
-
(** Create simple waypoint *)
24
-
let make_waypoint ~fs:_ ~lat ~lon ?name ?desc () =
25
-
match (Gpx.Coordinate.latitude lat, Gpx.Coordinate.longitude lon) with
26
-
| (Ok lat, Ok lon) ->
27
-
let wpt = Gpx.Waypoint.make lat lon in
28
-
{ wpt with name; desc }
29
-
| (Error e, _) | (_, Error e) -> failwith ("Invalid coordinate: " ^ e)
30
-
31
20
(** Pretty print GPX statistics *)
32
-
let print_stats gpx =
33
-
Format.printf "%a@." Gpx.Doc.pp_stats gpx
21
+
let print_stats sink gpx =
22
+
let buf = Buffer.create 256 in
23
+
let fmt = Format.formatter_of_buffer buf in
24
+
Format.fprintf fmt "%a@?" Gpx.Doc.pp_stats gpx;
25
+
Eio.Flow.copy_string (Buffer.contents buf) sink
+11
-23
lib/gpx_eio/gpx_eio.mli
+11
-23
lib/gpx_eio/gpx_eio.mli
···
1
-
(** {1 GPX Eio - High-level Eio API for GPX operations}
1
+
(** {1 Eio API for GPX operations}
2
2
3
-
This module provides a high-level API for GPX operations using Eio's
3
+
This module provides a direct-style API for GPX operations using Eio's
4
4
effects-based concurrent I/O system. It offers convenient functions
5
5
for common GPX operations while maintaining structured concurrency.
6
6
···
13
13
let fs = Eio.Stdenv.fs env in
14
14
15
15
(* Create a GPX document *)
16
-
let lat = Gpx.latitude 37.7749 |> Result.get_ok in
17
-
let lon = Gpx.longitude (-122.4194) |> Result.get_ok in
18
-
let wpt = make_waypoint fs ~lat:(Gpx.latitude_to_float lat) ~lon:(Gpx.longitude_to_float lon) ~name:"San Francisco" () in
19
-
let gpx = Gpx.make_gpx ~creator:"eio-example" in
20
-
let gpx = { gpx with waypoints = [wpt] } in
16
+
let lat = Gpx.Coordinate.latitude 37.7749 |> Result.get_ok in
17
+
let lon = Gpx.Coordinate.longitude (-122.4194) |> Result.get_ok in
18
+
let wpt = Gpx.Waypoint.make lat lon |> Gpx.Waypoint.with_name "San Francisco" in
19
+
let gpx = Gpx.make_gpx ~creator:"eio-example" |> Gpx.Doc.add_waypoint wpt in
21
20
22
21
(* Write with validation *)
23
22
write ~validate:true fs "output.gpx" gpx;
24
23
25
24
(* Read it back *)
26
25
let gpx2 = read ~validate:true fs "output.gpx" in
27
-
Printf.printf "Read %d waypoints\n" (List.length gpx2.waypoints)
26
+
Printf.printf "Read %d waypoints\n" (List.length (Gpx.Doc.waypoints gpx2))
28
27
29
28
let () = Eio_main.run main
30
29
]}
···
36
35
37
36
(** {2 Convenience File Operations}
38
37
39
-
These functions provide simple file I/O with the filesystem from [Eio.Stdenv.fs]. *)
38
+
These functions provide simple file I/O with the filesystem from {!Eio.Stdenv.fs}. *)
40
39
41
40
(** Read and parse GPX file.
42
41
@param fs Filesystem capability
···
81
80
@raises Gpx.Gpx_error on write failure *)
82
81
val to_sink : ?validate:bool -> [> Eio.Flow.sink_ty ] Eio.Resource.t -> Gpx.t -> unit
83
82
84
-
(** {2 Utility Functions} *)
85
-
86
-
(** Create simple waypoint with coordinates.
87
-
@param fs Filesystem capability (unused, for API consistency)
88
-
@param lat Latitude in degrees
89
-
@param lon Longitude in degrees
90
-
@param ?name Optional waypoint name
91
-
@param ?desc Optional waypoint description
92
-
@return Waypoint data
93
-
@raises Gpx.Gpx_error on invalid coordinates *)
94
-
val make_waypoint : fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> lat:float -> lon:float -> ?name:string -> ?desc:string -> unit -> Gpx.Waypoint.t
95
-
96
-
(** Print GPX statistics to stdout.
83
+
(** Print GPX statistics to sink.
84
+
@param sink Output sink
97
85
@param gpx GPX document *)
98
-
val print_stats : Gpx.t -> unit
86
+
val print_stats : [> Eio.Flow.sink_ty ] Eio.Resource.t -> Gpx.t -> unit
+1
-3
lib/gpx_eio/gpx_io.ml
+1
-3
lib/gpx_eio/gpx_io.ml
···
1
1
(** GPX Eio I/O operations *)
2
2
3
-
(* Real Eio-based I/O operations *)
4
-
5
3
(** Read GPX from file path *)
6
4
let read_file ?(validate=false) ~fs path =
7
5
let content = Eio.Path.load Eio.Path.(fs / path) in
···
71
69
Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / path) backup_content
72
70
with _ -> () (* Ignore restore errors *)
73
71
);
74
-
raise err
72
+
raise err
+2
-26
lib/gpx_unix/gpx_unix.ml
+2
-26
lib/gpx_unix/gpx_unix.ml
···
1
-
(** High-level Unix API for GPX operations *)
1
+
(** Unix API for GPX operations *)
2
2
3
-
(* Re-export IO module *)
4
3
module IO = Gpx_io
5
-
6
-
(* Re-export common types *)
7
4
open Gpx
8
5
9
6
(** Convenience functions for common operations *)
···
17
14
(** Write GPX to file with backup *)
18
15
let write_with_backup = IO.write_file_with_backup
19
16
20
-
(** Convert GPX to string *)
21
-
let to_string = write_string
22
-
23
-
(** Parse GPX from string *)
24
-
let from_string = parse_string
25
-
26
-
(** Quick validation check *)
27
-
let is_valid = is_valid
28
-
29
-
(** Get validation issues *)
30
-
let validate = validate_gpx
31
-
32
-
(** Create simple waypoint *)
33
-
let make_waypoint ~lat ~lon ?name ?desc () =
34
-
match (Coordinate.latitude lat, Coordinate.longitude lon) with
35
-
| (Ok lat, Ok lon) ->
36
-
let wpt = Waypoint.make lat lon in
37
-
let wpt = { wpt with name; desc } in
38
-
Ok wpt
39
-
| (Error e, _) | (_, Error e) -> Error (Gpx.Error.invalid_coordinate e)
40
-
41
17
(** Pretty print GPX statistics *)
42
18
let print_stats gpx =
43
-
Format.printf "%a@." Doc.pp_stats gpx
19
+
Format.printf "%a@." Doc.pp_stats gpx
+2
-23
lib/gpx_unix/gpx_unix.mli
+2
-23
lib/gpx_unix/gpx_unix.mli
···
1
-
(** High-level Unix API for GPX operations *)
1
+
(** Unix API for GPX operations *)
2
2
3
-
(* Re-export IO module *)
4
-
module IO = Gpx_io
5
-
6
-
(* Re-export common types *)
7
3
open Gpx
8
4
9
-
(** Convenience functions for common operations *)
10
-
11
5
(** Read and parse GPX file *)
12
6
val read : ?validate:bool -> string -> (t, error) result
13
7
···
17
11
(** Write GPX to file with backup *)
18
12
val write_with_backup : ?validate:bool -> string -> t -> (string, error) result
19
13
20
-
(** Convert GPX to string *)
21
-
val to_string : ?validate:bool -> t -> (string, error) result
22
-
23
-
(** Parse GPX from string *)
24
-
val from_string : ?validate:bool -> string -> (t, error) result
25
-
26
-
(** Quick validation check *)
27
-
val is_valid : t -> bool
28
-
29
-
(** Get validation issues *)
30
-
val validate : t -> validation_result
31
-
32
-
(** Create simple waypoint *)
33
-
val make_waypoint : lat:float -> lon:float -> ?name:string -> ?desc:string -> unit -> (Waypoint.t, error) result
34
-
35
14
(** Pretty print GPX statistics *)
36
-
val print_stats : t -> unit
15
+
val print_stats : t -> unit