-
Notifications
You must be signed in to change notification settings - Fork 5
More robust reading of filenames #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| val parse : string -> (string option, string) result | ||
| (** [parse s] parses [s] and returns a filename or [None] if the filename | ||
| is equivalent to [/dev/null]. | ||
| Returns [Error msg] in case of error. *) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure if this is a clear API, when I get I know I started with this idea originally, but I think returning There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This module is not accessible outside of the patch library so i think we should rather make the internal API consistent with the rest of the code which expects an option (until someone proposes something better, although i'm personally fine with the current state of things) |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| { | ||
| module String = Patch_lib.String | ||
|
|
||
| type lexer_output = | ||
| | Quoted of string | ||
| | Unquoted | ||
| | Error of string | ||
|
|
||
| exception Cant_parse_octal | ||
|
|
||
| let ascii_zero = Char.code '0' | ||
| let octal_to_char c1 c2 c3 = | ||
| let char_to_digit c = Char.code c - ascii_zero in | ||
| try | ||
| Char.chr ( | ||
| (char_to_digit c1 lsl 6) lor | ||
| (char_to_digit c2 lsl 3) lor | ||
| char_to_digit c3 | ||
| ) | ||
| with Invalid_argument _ -> raise Cant_parse_octal | ||
| } | ||
|
|
||
| let octal = ['0'-'7'] | ||
|
|
||
| rule lex_quoted_filename buf = parse | ||
| | "\\a" { Buffer.add_char buf '\007'; lex_quoted_filename buf lexbuf } | ||
| | "\\b" { Buffer.add_char buf '\b'; lex_quoted_filename buf lexbuf } | ||
| | "\\f" { Buffer.add_char buf '\012'; lex_quoted_filename buf lexbuf } | ||
| | "\\n" { Buffer.add_char buf '\n'; lex_quoted_filename buf lexbuf } | ||
| | "\\r" { Buffer.add_char buf '\r'; lex_quoted_filename buf lexbuf } | ||
| | "\\t" { Buffer.add_char buf '\t'; lex_quoted_filename buf lexbuf } | ||
| | "\\v" { Buffer.add_char buf '\011'; lex_quoted_filename buf lexbuf } | ||
| | "\\\\" { Buffer.add_char buf '\\'; lex_quoted_filename buf lexbuf } | ||
| | "\\\"" { Buffer.add_char buf '"'; lex_quoted_filename buf lexbuf } | ||
| | '\\' (['0'-'3'] as c1) (octal as c2) (octal as c3) | ||
| { | ||
| match octal_to_char c1 c2 c3 with | ||
| | octal -> | ||
| Buffer.add_char buf octal; | ||
| lex_quoted_filename buf lexbuf | ||
| | exception Cant_parse_octal -> Unquoted | ||
| } | ||
| | '\\' _ { Unquoted } | ||
| | '"' eof { Quoted (Buffer.contents buf) } | ||
| | '"' _ { Unquoted } | ||
| | _ as c { Buffer.add_char buf c; lex_quoted_filename buf lexbuf } | ||
| | eof { Unquoted } | ||
|
|
||
| and lex_filename buf = parse | ||
| | '"' { lex_quoted_filename buf lexbuf } | ||
| | _ { Unquoted } | ||
| | eof { Error "empty filename" } | ||
|
|
||
| { | ||
| let parse s = | ||
| let filename, date = | ||
| match String.cut '\t' s with | ||
| | None -> (s, "") | ||
| | Some x -> x | ||
| in | ||
| if filename = "/dev/null" || | ||
| String.is_prefix ~prefix:"1970-" date || | ||
| String.is_prefix ~prefix:"1969-" date || | ||
| String.is_suffix ~suffix:" 1970" date || | ||
| String.is_suffix ~suffix:" 1969" date then | ||
| (* See https://github.com/hannesm/patch/issues/8 *) | ||
| Ok None | ||
| else | ||
| let lexbuf = Lexing.from_string filename in | ||
| match lex_filename (Buffer.create 128) lexbuf with | ||
| | Quoted x -> Ok (Some x) | ||
| | Unquoted -> Ok (Some filename) | ||
| | Error msg -> Error msg | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| module String = struct | ||
| let is_prefix ~prefix str = | ||
| let pl = String.length prefix in | ||
| if String.length str < pl then | ||
| false | ||
| else | ||
| String.sub str 0 (String.length prefix) = prefix | ||
|
|
||
| let is_suffix ~suffix str = | ||
| let pl = String.length suffix in | ||
| if String.length str < pl then | ||
| false | ||
| else | ||
| String.sub str (String.length str - pl) pl = suffix | ||
|
|
||
| let cut sep str = | ||
| try | ||
| let idx = String.index str sep | ||
| and l = String.length str | ||
| in | ||
| let sidx = succ idx in | ||
| Some (String.sub str 0 idx, String.sub str sidx (l - sidx)) | ||
| with | ||
| Not_found -> None | ||
|
|
||
| let cuts sep str = | ||
| let rec doit acc s = | ||
| match cut sep s with | ||
| | None -> List.rev (s :: acc) | ||
| | Some (a, b) -> doit (a :: acc) b | ||
| in | ||
| doit [] str | ||
|
|
||
| let slice ?(start = 0) ?stop str = | ||
| let stop = match stop with | ||
| | None -> String.length str | ||
| | Some x -> x | ||
| in | ||
| let len = stop - start in | ||
| String.sub str start len | ||
|
|
||
| let trim = String.trim | ||
|
|
||
| let get = String.get | ||
|
|
||
| let concat = String.concat | ||
|
|
||
| let length = String.length | ||
|
|
||
| let equal = String.equal | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| module String : sig | ||
| val is_prefix : prefix:string -> string -> bool | ||
| val is_suffix : suffix:string -> string -> bool | ||
| val cut : char -> string -> (string * string) option | ||
| val cuts : char -> string -> string list | ||
| val slice : ?start:int -> ?stop:int -> string -> string | ||
| val trim : string -> string | ||
| val get : string -> int -> char | ||
| val concat : string -> string list -> string | ||
| val length : string -> int | ||
| val equal : string -> string -> bool | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suggestion would be dropping this and just moving the executable into a different folder, thus new modules would be picked up automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be done later