package cosovo

  1. Overview
  2. Docs
An OCaml library parsing CSV files

Install

dune-project
 Dependency

Authors

Maintainers

Sources

cosovo-3.tbz
sha256=fca9a6d3ad87bbffa483417424b858db69ab4bf7407459ddbb52accf4f368ef1
sha512=5bf77898c9a3be21df6faf1cbd66f881adf4fc29155e02b289ac07215ed33645a6b23375876ce81bff922632fcab2fc1e4b214b76155532d4697b64f9b089630

doc/src/cosovo/iO.ml.html

Source file 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
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
type error_location = {
  e_line_number : int;
  e_start : int;
  e_end : int
}

let error_location lexbuf =
  let open Lexing in
  let pos1 = lexbuf.lex_start_p in
  let pos2 = lexbuf.lex_curr_p in
  let line1 = pos1.pos_lnum
  and start1 = pos1.pos_bol in
  {
    e_line_number = line1;
    e_start = pos1.pos_cnum - start1;
    e_end = pos2.pos_cnum - start1
  }

let string_of_error_location {e_line_number; e_start; e_end} =
  Printf.sprintf "error at line %d, characters %d-%d\n" e_line_number
    e_start e_end

type error = [
  | `SyntaxError of error_location
  | `UnterminatedString of int (* line number *)
  | `IntOverflow of (int * string) (* line number and offending string *)
]

type value = [ `Int of int | `Float of float | `String of string ]
type dense = value list
type sparse = (int * value) list

type row = [`Sparse of sparse | `Dense of dense ]
type row_or_error = (row, error) result
type header = [`Sparse of (int * string) list | `Dense of string list]

let string_of_error = function
  | `SyntaxError err ->
    Printf.sprintf "syntax error: %s" (string_of_error_location err)

  | `UnterminatedString line ->
    Printf.sprintf "unterminated string on line %d" line

  | `IntOverflow (line, offending_string) ->
    Printf.sprintf "value %S on line %d cannot be represented as an integer"
      offending_string line

type row_seq = row_or_error Seq.t

let of_channel ~no_header ch =
  let lexbuf = Lexing.from_channel ch in
  try
    let h =
      if not no_header then
        Parser.header Lexer.header lexbuf
      else
        None
    in
    let open Seq in
    let rec row () =
      try
        match Parser.row Lexer.row lexbuf with
        | `EOF -> Nil
        | `Dense d -> Cons (Ok (`Dense d), row)
        | `Sparse s -> Cons (Ok (`Sparse s), row)
      with
        | Parser.Error ->
          Cons (Error (`SyntaxError (error_location lexbuf)), fun () -> Nil)
        | Lexer.UnterminatedString line ->
          Cons (Error (`UnterminatedString line), fun () -> Nil)
        | Lexer.IntOverflow line_and_offending_string ->
          Cons (Error (`IntOverflow line_and_offending_string), fun () -> Nil)
    in
    Ok (h, row)

  with
    | Parser.Error ->
      Error (`SyntaxError (error_location lexbuf))
    | Lexer.UnterminatedString line ->
      Error (`UnterminatedString line)
    | Lexer.IntOverflow line_and_offending_string ->
      Error (`IntOverflow line_and_offending_string)


let row_of_string string =
  let lexbuf = Lexing.from_string string in
  try
    match Parser.row_sans_nl Lexer.row lexbuf with
    | `EOF -> Error `EOF
    | `Sparse sparse -> Ok (`Sparse sparse)
    | `Dense dense -> Ok (`Dense dense)
  with
  | Parsing.Parse_error ->
    Error (`SyntaxError (error_location lexbuf))
  | Lexer.UnterminatedString line ->
    Error (`UnterminatedString line)
  | Lexer.IntOverflow line_and_offending_string ->
    Error (`IntOverflow line_and_offending_string)
OCaml

Innovation. Community. Security.