mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
remove cgi/; move sub-libraries to their own subdir each; mv everything into src/
This commit is contained in:
parent
eda9b08c1d
commit
61465fa19a
160 changed files with 72 additions and 629 deletions
38
.merlin
38
.merlin
|
|
@ -1,17 +1,31 @@
|
|||
S core
|
||||
S misc
|
||||
S string
|
||||
S pervasives
|
||||
S tests
|
||||
S examples
|
||||
S src/core
|
||||
S src/data/
|
||||
S src/io
|
||||
S src/iter/
|
||||
S src/advanced/
|
||||
S src/lwt/
|
||||
S src/sexp/
|
||||
S src/threads/
|
||||
S src/misc
|
||||
S src/string
|
||||
S src/pervasives
|
||||
S benchs
|
||||
B _build/core
|
||||
B _build/misc
|
||||
B _build/string
|
||||
B _build/pervasives
|
||||
B _build/tests
|
||||
S examples
|
||||
S tests
|
||||
B _build/src/core
|
||||
B _build/src/data/
|
||||
B _build/src/io
|
||||
B _build/src/iter/
|
||||
B _build/src/advanced/
|
||||
B _build/src/lwt/
|
||||
B _build/src/sexp/
|
||||
B _build/src/threads/
|
||||
B _build/src/misc
|
||||
B _build/src/string
|
||||
B _build/src/pervasives
|
||||
B _build/benchs
|
||||
B _build/examples
|
||||
B _build/benchs/
|
||||
B _build/tests
|
||||
PKG oUnit
|
||||
PKG benchmark
|
||||
PKG threads
|
||||
|
|
|
|||
61
_oasis
61
_oasis
|
|
@ -42,46 +42,48 @@ Flag "bench"
|
|||
Default: false
|
||||
|
||||
Library "containers"
|
||||
Path: core
|
||||
Path: src/core
|
||||
Modules: CCVector, CCPrint, CCError, CCHeap, CCList, CCOpt, CCPair,
|
||||
CCFun, CCHash, CCInt, CCBool, CCFloat, CCArray,
|
||||
CCOrd, CCRandom, CCString, CCHashtbl, CCMap
|
||||
BuildDepends: bytes
|
||||
|
||||
Library "containers_io"
|
||||
Path: core
|
||||
Path: src/io
|
||||
Modules: CCIO
|
||||
BuildDepends: bytes
|
||||
FindlibParent: containers
|
||||
FindlibName: io
|
||||
|
||||
Library "containers_sexp"
|
||||
Path: core
|
||||
Path: src/sexp
|
||||
Modules: CCSexp
|
||||
BuildDepends: bytes
|
||||
FindlibParent: containers
|
||||
FindlibName: sexp
|
||||
|
||||
Library "containers_data"
|
||||
Path: core
|
||||
Path: src/data
|
||||
Modules: CCMultiMap, CCMultiSet, CCTrie, CCFlatHashtbl, CCCache,
|
||||
CCPersistentHashtbl, CCDeque, CCFQueue, CCBV
|
||||
CCPersistentHashtbl, CCDeque, CCFQueue, CCBV, CCMixtbl
|
||||
FindlibParent: containers
|
||||
FindlibName: data
|
||||
|
||||
Library "containers_iter"
|
||||
Path: core
|
||||
Path: src/iter
|
||||
Modules: CCKTree, CCKList
|
||||
FindlibParent: containers
|
||||
FindlibName: iter
|
||||
|
||||
Library "containers_string"
|
||||
Path: string
|
||||
Path: src/string
|
||||
Pack: true
|
||||
Modules: KMP, Levenshtein
|
||||
FindlibName: string
|
||||
FindlibParent: containers
|
||||
|
||||
Library "containers_advanced"
|
||||
Path: advanced
|
||||
Path: src/advanced
|
||||
Pack: true
|
||||
Modules: CCLinq, CCBatch, CCCat, CCMonadIO
|
||||
FindlibName: advanced
|
||||
|
|
@ -89,27 +91,27 @@ Library "containers_advanced"
|
|||
BuildDepends: containers, sequence
|
||||
|
||||
Library "containers_pervasives"
|
||||
Path: pervasives
|
||||
Path: src/pervasives
|
||||
Modules: CCPervasives
|
||||
BuildDepends: containers
|
||||
FindlibName: pervasives
|
||||
FindlibParent: containers
|
||||
|
||||
Library "containers_misc"
|
||||
Path: misc
|
||||
Path: src/misc
|
||||
Pack: true
|
||||
Modules: FHashtbl, FlatHashtbl, Hashset,
|
||||
Heap, LazyGraph, PersistentGraph,
|
||||
PHashtbl, SkipList, SplayTree, SplayMap, Univ,
|
||||
Bij, PiCalculus, RAL, UnionFind, SmallSet, AbsSet, CSM,
|
||||
TTree, PrintBox, HGraph, Automaton, Conv, Bidir, Iteratee,
|
||||
BTree, Ty, Cause, AVL, ParseReact, Mixtbl
|
||||
BuildDepends: unix,containers
|
||||
BTree, Ty, Cause, AVL, ParseReact
|
||||
BuildDepends: unix, containers, containers.data
|
||||
FindlibName: misc
|
||||
FindlibParent: containers
|
||||
|
||||
Library "containers_thread"
|
||||
Path: threads/
|
||||
Path: src/threads/
|
||||
Modules: CCFuture
|
||||
FindlibName: thread
|
||||
FindlibParent: containers
|
||||
|
|
@ -119,7 +121,7 @@ Library "containers_thread"
|
|||
XMETARequires: containers,threads
|
||||
|
||||
Library "containers_lwt"
|
||||
Path: lwt
|
||||
Path: src/lwt
|
||||
Modules: Lwt_automaton, Lwt_actor
|
||||
Pack: true
|
||||
FindlibName: lwt
|
||||
|
|
@ -128,16 +130,6 @@ Library "containers_lwt"
|
|||
Install$: flag(lwt) && flag(misc)
|
||||
BuildDepends: containers, lwt, containers.misc
|
||||
|
||||
Library "containers_cgi"
|
||||
Path: cgi
|
||||
Modules: ToWeb
|
||||
FindlibName: cgi
|
||||
FindlibParent: containers
|
||||
Build$: flag(cgi)
|
||||
Install$: flag(cgi)
|
||||
BuildDepends: containers,CamlGI
|
||||
XMETARequires: containers,CamlGI
|
||||
|
||||
Document containers
|
||||
Title: Containers docs
|
||||
Type: ocamlbuild (0.3)
|
||||
|
|
@ -148,7 +140,8 @@ Document containers
|
|||
"-docflags '-colorize-code -short-functors -charset utf-8'"
|
||||
XOCamlbuildLibraries:
|
||||
containers, containers.misc, containers.iter, containers.data,
|
||||
containers.string, containers.advanced, containers.io, containers.sexp,
|
||||
containers.string, containers.pervasives,
|
||||
containers.advanced, containers.io, containers.sexp,
|
||||
containers.lwt
|
||||
|
||||
|
||||
|
|
@ -159,7 +152,8 @@ Executable run_benchs
|
|||
Build$: flag(bench) && flag(misc)
|
||||
MainIs: run_benchs.ml
|
||||
BuildDepends: containers, containers.misc, containers.advanced,
|
||||
containers.string, sequence, gen, benchmark
|
||||
containers.data, containers.string, containers.iter,
|
||||
sequence, gen, benchmark
|
||||
|
||||
Executable bench_hash
|
||||
Path: benchs/
|
||||
|
|
@ -167,7 +161,7 @@ Executable bench_hash
|
|||
CompiledObject: native
|
||||
Build$: flag(bench) && flag(misc)
|
||||
MainIs: bench_hash.ml
|
||||
BuildDepends: containers,containers.misc
|
||||
BuildDepends: containers, containers.misc
|
||||
|
||||
Executable bench_conv
|
||||
Path: benchs/
|
||||
|
|
@ -175,7 +169,7 @@ Executable bench_conv
|
|||
CompiledObject: native
|
||||
Build$: flag(bench)
|
||||
MainIs: bench_conv.ml
|
||||
BuildDepends: containers,benchmark,gen
|
||||
BuildDepends: containers, benchmark, gen
|
||||
|
||||
Executable test_levenshtein
|
||||
Path: tests/
|
||||
|
|
@ -183,7 +177,7 @@ Executable test_levenshtein
|
|||
CompiledObject: native
|
||||
Build$: flag(tests)
|
||||
MainIs: test_levenshtein.ml
|
||||
BuildDepends: containers,qcheck,containers.string
|
||||
BuildDepends: containers, qcheck, containers.string
|
||||
|
||||
Executable test_threads
|
||||
Path: tests/lwt/
|
||||
|
|
@ -191,7 +185,7 @@ Executable test_threads
|
|||
CompiledObject: best
|
||||
Build$: flag(tests) && flag(thread)
|
||||
MainIs: test_Future.ml
|
||||
BuildDepends: containers,threads,oUnit,containers.lwt
|
||||
BuildDepends: containers, threads, oUnit, containers.lwt
|
||||
|
||||
PreBuildCommand: make qtest-gen
|
||||
|
||||
|
|
@ -210,7 +204,8 @@ Executable run_tests
|
|||
CompiledObject: native
|
||||
MainIs: run_tests.ml
|
||||
Build$: flag(tests) && flag(misc)
|
||||
BuildDepends: containers, oUnit, sequence, gen, qcheck, containers.misc
|
||||
BuildDepends: containers, containers.data, oUnit, sequence, gen,
|
||||
qcheck, containers.misc
|
||||
|
||||
Test all
|
||||
Command: make test-all
|
||||
|
|
@ -229,7 +224,7 @@ Executable lambda
|
|||
Install: false
|
||||
MainIs: lambda.ml
|
||||
Build$: flag(misc)
|
||||
BuildDepends: containers,containers.misc
|
||||
BuildDepends: containers, containers.misc
|
||||
|
||||
Executable id_sexp
|
||||
Path: examples/
|
||||
|
|
@ -237,7 +232,7 @@ Executable id_sexp
|
|||
CompiledObject: native
|
||||
MainIs: id_sexp.ml
|
||||
Build$: flag(misc)
|
||||
BuildDepends: containers
|
||||
BuildDepends: containers.sexp
|
||||
|
||||
SourceRepository head
|
||||
Type: git
|
||||
|
|
|
|||
8
_tags
8
_tags
|
|
@ -158,9 +158,7 @@
|
|||
<examples/*.ml{,i}>: use_containers_misc
|
||||
# OASIS_STOP
|
||||
<tests/*.ml{,i}>: thread
|
||||
<threads/*.ml{,i}>: thread
|
||||
<sequence>: -traverse
|
||||
<gen>: -traverse
|
||||
<core/CCVector.cmx>: inline(25)
|
||||
<{string,core}/**/*.ml>: warn_A, warn(-4), warn(-44)
|
||||
<src/threads/*.ml{,i}>: thread
|
||||
<src/core/CCVector.cmx>: inline(25)
|
||||
<src/{string,core}/**/*.ml>: warn_A, warn(-4), warn(-44)
|
||||
true: no_alias_deps
|
||||
|
|
|
|||
358
cgi/toWeb.ml
358
cgi/toWeb.ml
|
|
@ -1,358 +0,0 @@
|
|||
|
||||
(*
|
||||
copyright (c) 2013, simon cruanes
|
||||
all rights reserved.
|
||||
|
||||
redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer. redistributions in binary
|
||||
form must reproduce the above copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*)
|
||||
|
||||
(** {1 Expose the State of a Program to the Web}
|
||||
|
||||
We export some values (and associated functions for converting them to
|
||||
html, and update them) as a FastCGI interface.
|
||||
|
||||
This module depends on CamlGI.
|
||||
*)
|
||||
|
||||
(** {2 Some combinators to build HTML documents} *)
|
||||
|
||||
module HTML = struct
|
||||
type t =
|
||||
| Str of string (* content *)
|
||||
| List of t list
|
||||
| Url of url
|
||||
| Img of image
|
||||
| Concat of t list
|
||||
| H of int * t
|
||||
| Link of link
|
||||
| Tag of string * t
|
||||
| TagWith of string * (string * string) list * t
|
||||
and url = {
|
||||
url_alt : string option;
|
||||
url_url : string;
|
||||
url_descr : string;
|
||||
}
|
||||
and image = {
|
||||
img_alt : string option;
|
||||
img_url : string;
|
||||
}
|
||||
and link = {
|
||||
link_rel : string;
|
||||
link_url : string;
|
||||
}
|
||||
|
||||
let str s = Str s
|
||||
|
||||
let bprintf format =
|
||||
let buffer = Buffer.create 64 in
|
||||
let r = ref (str "") in
|
||||
Printf.kbprintf
|
||||
(fun x -> r := str (Buffer.contents buffer))
|
||||
buffer
|
||||
format;
|
||||
!r
|
||||
|
||||
let sprintf format =
|
||||
let r = ref (str "") in
|
||||
Printf.ksprintf
|
||||
(fun s -> r := str s)
|
||||
format;
|
||||
!r
|
||||
|
||||
let list l = List l
|
||||
|
||||
let url ?alt ~url ~descr = Url {
|
||||
url_alt = alt;
|
||||
url_url = url;
|
||||
url_descr = descr;
|
||||
}
|
||||
|
||||
let img ?alt url = Img {
|
||||
img_alt = alt;
|
||||
img_url = url;
|
||||
}
|
||||
|
||||
let append a b = Concat [a; b]
|
||||
|
||||
let concat l = Concat l
|
||||
|
||||
let h1 x = H (1, x)
|
||||
|
||||
let h2 x = H (2, x)
|
||||
|
||||
let h3 x = H (3, x)
|
||||
|
||||
let h n x = H (n, x)
|
||||
|
||||
let p x = Tag ("p", x)
|
||||
|
||||
let div ?id ?class_ x =
|
||||
match id, class_ with
|
||||
| None, None -> Tag ("div", x)
|
||||
| Some i, None -> TagWith ("div", ["id", i], x)
|
||||
| None, Some c -> TagWith ("div", ["class", c], x)
|
||||
| Some i, Some c -> TagWith ("div", ["id", i; "class", c], x)
|
||||
|
||||
let span ?id ?class_ x =
|
||||
match id, class_ with
|
||||
| None, None -> Tag ("span", x)
|
||||
| Some i, None -> TagWith ("span", ["id", i], x)
|
||||
| None, Some c -> TagWith ("span", ["class", c], x)
|
||||
| Some i, Some c -> TagWith ("span", ["id", i; "class", c], x)
|
||||
|
||||
let link ~rel ~url = Link {
|
||||
link_rel = rel;
|
||||
link_url = url;
|
||||
}
|
||||
|
||||
let head x = Tag ("head", x)
|
||||
|
||||
let body x = Tag ("body", x)
|
||||
|
||||
let html x = Tag ("html", x)
|
||||
|
||||
let _to_hex n = match n with
|
||||
| _ when n >= 0 && n < 10 -> Char.chr (Char.code '0' + n)
|
||||
| 10 -> 'A'
|
||||
| 11 -> 'B'
|
||||
| 12 -> 'C'
|
||||
| 13 -> 'D'
|
||||
| 14 -> 'E'
|
||||
| 15 -> 'F'
|
||||
| _ -> failwith "not an hexadecimal digit"
|
||||
|
||||
let _encode_char buf c =
|
||||
Buffer.add_string buf "&#x";
|
||||
let h, l = Char.code c / 16, Char.code c mod 16 in
|
||||
Buffer.add_char buf (_to_hex h);
|
||||
Buffer.add_char buf (_to_hex l)
|
||||
|
||||
let encode str =
|
||||
let b = Buffer.create (String.length str + 10) in
|
||||
for i = 0 to String.length str - 1 do
|
||||
match str.[i] with
|
||||
| ';' | '/' | '?' | ':' | '@' | '&' | '=' | '+' | '$' | ',' | '<'
|
||||
| '>' | '#' | '%' | '"' | '{' | '}' | '|' | '\\' | '^' | '[' | ']'
|
||||
| '`' -> _encode_char b str.[i]
|
||||
| c when Char.code c < 32 -> _encode_char b str.[i]
|
||||
| c when Char.code c > 127 -> _encode_char b str.[i]
|
||||
| _ -> Buffer.add_char b str.[i]
|
||||
done;
|
||||
Buffer.contents b
|
||||
|
||||
(* real rendering is always into a buffer (for now) *)
|
||||
let rec to_buf buf x =
|
||||
match x with
|
||||
| Str s -> Buffer.add_string buf (encode s)
|
||||
| List l ->
|
||||
Buffer.add_string buf "<ul>";
|
||||
List.iter
|
||||
(fun y -> Printf.bprintf buf "<li>%a</li>" to_buf y)
|
||||
l;
|
||||
Buffer.add_string buf "</ul>"
|
||||
| Url url ->
|
||||
begin match url.url_alt with
|
||||
| None ->
|
||||
Printf.bprintf buf "<a href=\"%s\">%s</a>" url.url_url
|
||||
(encode url.url_descr)
|
||||
| Some alt ->
|
||||
Printf.bprintf buf "<a href=\"%s\" alt=\"%s\">%s</a>"
|
||||
url.url_url (encode alt) (encode url.url_descr)
|
||||
end
|
||||
| Img i -> failwith "img: not implemented"
|
||||
| Concat l ->
|
||||
List.iteri
|
||||
(fun i y ->
|
||||
if i > 0 then Buffer.add_char buf ' ';
|
||||
to_buf buf y)
|
||||
l
|
||||
| H (n, y) ->
|
||||
Printf.bprintf buf "<h%i> %a </h%i>" n to_buf y n
|
||||
| Link _ -> failwith "link: not implemented"
|
||||
| Tag (str, y) -> Printf.bprintf buf "<%s> %a </%s>" str to_buf y str
|
||||
| TagWith (str, attrs, y) ->
|
||||
Printf.bprintf buf "<%s " str;
|
||||
List.iter (fun (name,attr) -> Printf.bprintf buf "%s=\"%s\"" name attr) attrs;
|
||||
Printf.bprintf buf "> %a </%s>" to_buf y str
|
||||
|
||||
let render x =
|
||||
let buf = Buffer.create 256 in
|
||||
to_buf buf x;
|
||||
Buffer.contents buf
|
||||
|
||||
let to_chan oc x =
|
||||
let buf = Buffer.create 256 in
|
||||
to_buf buf x;
|
||||
Buffer.output_buffer oc buf
|
||||
end
|
||||
|
||||
(** {2 Stateful Object on the Web} *)
|
||||
|
||||
module State = struct
|
||||
type 'a t = {
|
||||
mutable content : 'a;
|
||||
mutable callbacks : ('a -> unit) list;
|
||||
id : ('a -> string) option;
|
||||
export : 'a -> HTML.t;
|
||||
update : (string * string) list -> 'a -> 'a;
|
||||
} (** A value that can be exposed to the Web.
|
||||
The [export] function is used to print the current state of
|
||||
the object into HTML (when requested).
|
||||
The [update] optional function can be used to update
|
||||
the value, given a query with parameters. *)
|
||||
|
||||
type wrap = Wrap : 'a t -> wrap
|
||||
(** Hides the type parameter in a GADT. *)
|
||||
|
||||
let create ?(update=fun _ x -> x) ?id ~export content = {
|
||||
content;
|
||||
export;
|
||||
id;
|
||||
callbacks = [];
|
||||
update;
|
||||
}
|
||||
|
||||
let on_change st f =
|
||||
st.callbacks <- f :: st.callbacks
|
||||
|
||||
let handle_request st req =
|
||||
let cgi = new CamlGI.Cgi.cgi req in
|
||||
(* update value? *)
|
||||
try
|
||||
let x = st.content in
|
||||
let params = cgi#params in
|
||||
(* update [x] using the parameters? *)
|
||||
let y = st.update params x in
|
||||
let changed = match st.id with
|
||||
| None -> x != y
|
||||
| Some id -> id x <> id y
|
||||
in
|
||||
(* notify callbacks that we have a new object *)
|
||||
if changed then
|
||||
List.iter (fun f -> f y) st.callbacks;
|
||||
(* now print [y] *)
|
||||
(* TODO: add a head, declaration, etc. *)
|
||||
let html = st.export y in
|
||||
let final_output = HTML.render html in
|
||||
(* render output *)
|
||||
let template = object
|
||||
method output f = f final_output
|
||||
end in
|
||||
cgi#template template
|
||||
with e ->
|
||||
let msg = Printf.sprintf "error: %s" (Printexc.to_string e) in
|
||||
cgi#log msg
|
||||
end
|
||||
|
||||
(** {2 Routing} *)
|
||||
|
||||
module Router = struct
|
||||
type t = {
|
||||
mutable default : State.wrap;
|
||||
log : out_channel option;
|
||||
tbl : (string, State.wrap) Hashtbl.t;
|
||||
}
|
||||
|
||||
let __default =
|
||||
State.Wrap (State.create ~export:HTML.str "<no default handler>")
|
||||
|
||||
let _log router fmt = match router.log with
|
||||
| None ->
|
||||
Printf.ifprintf stdout fmt
|
||||
| Some oc ->
|
||||
Printf.kfprintf
|
||||
(fun oc ->
|
||||
output_char oc '\n';
|
||||
flush oc)
|
||||
oc
|
||||
fmt
|
||||
|
||||
let create ?(default=__default) ?log () =
|
||||
let router = {
|
||||
default;
|
||||
log;
|
||||
tbl = Hashtbl.create 15;
|
||||
} in
|
||||
_log router "new router created";
|
||||
router
|
||||
|
||||
let default router default =
|
||||
router.default <- default
|
||||
|
||||
let unregister router name =
|
||||
Hashtbl.remove router.tbl name
|
||||
|
||||
let register ?(weak=false) router name state =
|
||||
if Hashtbl.mem router.tbl name
|
||||
then failwith "Router: name already registered"
|
||||
else begin
|
||||
Hashtbl.add router.tbl name state;
|
||||
if weak then match state with
|
||||
| State.Wrap st ->
|
||||
Gc.finalise (fun _ -> unregister router name) st.State.content
|
||||
end
|
||||
|
||||
let add_list router l =
|
||||
List.iter
|
||||
(fun (name, state) -> register router name state)
|
||||
l
|
||||
|
||||
let to_list router =
|
||||
Hashtbl.fold
|
||||
(fun name state acc -> (name,state) :: acc)
|
||||
router.tbl []
|
||||
|
||||
let random_id () =
|
||||
CamlGI.Cgi.random_sessionid ()
|
||||
|
||||
let handle_request router req =
|
||||
let cgi = new CamlGI.Cgi.cgi req in
|
||||
let url = cgi#url () in
|
||||
let st =
|
||||
try
|
||||
let last_part_i = String.rindex url '/' in
|
||||
let last_part = String.sub url (last_part_i+1) (String.length url -last_part_i-1) in
|
||||
_log router "received request for url /%s" last_part;
|
||||
Hashtbl.find router.tbl last_part
|
||||
with Not_found ->
|
||||
router.default
|
||||
in
|
||||
match st with
|
||||
| State.Wrap st -> State.handle_request st req
|
||||
end
|
||||
|
||||
(** {2 Main Interface} *)
|
||||
|
||||
let serve_state ?sockfile ?sockaddr st =
|
||||
match sockfile with
|
||||
| None ->
|
||||
CamlGI.Cgi.register_script ?sockaddr (State.handle_request st)
|
||||
| Some f ->
|
||||
let sockaddr = Unix.ADDR_UNIX f in
|
||||
CamlGI.Cgi.register_script ~sockaddr (State.handle_request st)
|
||||
|
||||
let serve_router ?sockfile ?sockaddr router =
|
||||
match sockfile with
|
||||
| None ->
|
||||
CamlGI.Cgi.register_script ?sockaddr (Router.handle_request router)
|
||||
| Some f ->
|
||||
let sockaddr = Unix.ADDR_UNIX f in
|
||||
CamlGI.Cgi.register_script ~sockaddr (Router.handle_request router)
|
||||
208
cgi/toWeb.mli
208
cgi/toWeb.mli
|
|
@ -1,208 +0,0 @@
|
|||
|
||||
(*
|
||||
copyright (c) 2013, simon cruanes
|
||||
all rights reserved.
|
||||
|
||||
redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer. redistributions in binary
|
||||
form must reproduce the above copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*)
|
||||
|
||||
(** {1 Expose the State of a Program to the Web}
|
||||
|
||||
We export some values (and associated functions for converting them to
|
||||
html, and update them) as a FastCGI interface.
|
||||
|
||||
This module depends on CamlGI.
|
||||
*)
|
||||
|
||||
(** {2 Some combinators to build HTML documents} *)
|
||||
|
||||
module HTML : sig
|
||||
type t
|
||||
(** A html document. Encoding is assumed to be UTF8 for now. *)
|
||||
|
||||
val str : string -> t
|
||||
(** Simple string *)
|
||||
|
||||
val bprintf : ('a, Buffer.t, unit, unit) format4 -> t
|
||||
(** Use a buffer printer to render a string. Shortcut for {!str} *)
|
||||
|
||||
val sprintf : ('a, unit, string, unit) format4 -> t
|
||||
(** Use a string printer to render into a string. Shortcut for {!str} *)
|
||||
|
||||
val list : t list -> t
|
||||
(** Build a list of items *)
|
||||
|
||||
val url : ?alt:string -> url:string -> descr:string -> t
|
||||
(** build an URL tag. *)
|
||||
|
||||
val img : ?alt:string -> string -> t
|
||||
(** Link to an image *)
|
||||
|
||||
val append : t -> t -> t
|
||||
(** Concatenation of two documents *)
|
||||
|
||||
val concat : t list -> t
|
||||
(** Concatenation of html documents *)
|
||||
|
||||
val h1 : t -> t
|
||||
|
||||
val h2 : t -> t
|
||||
|
||||
val h3 : t -> t
|
||||
|
||||
val h : int -> t -> t
|
||||
(** Title of level parametrized by the integer *)
|
||||
|
||||
val p : t -> t
|
||||
(** Paragraph *)
|
||||
|
||||
val div : ?id:string -> ?class_:string -> t -> t
|
||||
(** Div tag, to specify a block *)
|
||||
|
||||
val span : ?id:string -> ?class_:string -> t -> t
|
||||
(** Non semantic tag, mostly useful for CSS *)
|
||||
|
||||
val link : rel:string -> url:string -> t
|
||||
(** Link (for head) *)
|
||||
|
||||
val head : t -> t
|
||||
(** Head part of a document *)
|
||||
|
||||
val body : t -> t
|
||||
(** Body part of a document *)
|
||||
|
||||
val html : t -> t
|
||||
(** The whole document *)
|
||||
|
||||
val render : t -> string
|
||||
(** Print into a string *)
|
||||
|
||||
val to_buf : Buffer.t -> t -> unit
|
||||
(** Print in the buffer *)
|
||||
|
||||
val to_chan : out_channel -> t -> unit
|
||||
(** Print on the channel *)
|
||||
end
|
||||
|
||||
(** {2 Stateful Object on the Web} *)
|
||||
|
||||
(** This module defines how to bundle an OCaml value (possibly
|
||||
stateful) with functions that export it to HTML,
|
||||
and possibly update it from a CGI request.
|
||||
*)
|
||||
|
||||
module State : sig
|
||||
type 'a t
|
||||
(** A value that can be exposed to the web. *)
|
||||
|
||||
type wrap = Wrap : 'a t -> wrap
|
||||
(** Hides the type parameter in a GADT. Useful for {!Router}. *)
|
||||
|
||||
val create : ?update:((string*string) list -> 'a -> 'a) ->
|
||||
?id:('a -> string) ->
|
||||
export:('a -> HTML.t) ->
|
||||
'a ->
|
||||
'a t
|
||||
(** Create a value that can be exposed to the Web.
|
||||
@param export function used to print the current state of
|
||||
the object into HTML (when requested).
|
||||
@param update optional function that can be used to update
|
||||
the value, given a query with parameters.
|
||||
@param id optional function that maps a value to a (unique)
|
||||
string. Can be used to obtain a unique URL for this value. *)
|
||||
|
||||
val on_change : 'a t -> ('a -> unit) -> unit
|
||||
(** Register a callback that will be called everytime the value
|
||||
is updated. Physical equality is used to determine whether
|
||||
the value changed if no [id] function was provided;
|
||||
otherwise, [id] is used to check whether the old and the new
|
||||
strings are equal. *)
|
||||
|
||||
val handle_request : 'a t -> CamlGI.Cgi.Request.t -> unit
|
||||
(** Handle the incoming request. It replies to the request by
|
||||
possibly updating the local state, and
|
||||
object. *)
|
||||
end
|
||||
|
||||
|
||||
(** {2 Routing} *)
|
||||
|
||||
module Router : sig
|
||||
type t
|
||||
(** An URL router. It dispatches incoming requests to registered
|
||||
{!State.t} values depending on the request's URL. *)
|
||||
|
||||
val create : ?default:State.wrap -> ?log:out_channel -> unit -> t
|
||||
(** New router.
|
||||
@param log a channel on which to log events (incoming requests)
|
||||
@param default a default object to expose, for incorrect routes
|
||||
*)
|
||||
|
||||
val default : t -> State.wrap -> unit
|
||||
(** Set the default handler, for incorrect routes (for which no
|
||||
object is registered) or for routing the root url *)
|
||||
|
||||
val register : ?weak:bool -> t -> string -> State.wrap -> unit
|
||||
(** Register a state object (see {!State}) under a given path.
|
||||
Right now routing only dispatches at one level, there is no
|
||||
tree-like structure, only a flat "directory" of objects.
|
||||
|
||||
@param weak (default false) if true, the object will unregister itself
|
||||
when it's garbage collected. Only works if the type of the wrapped
|
||||
object is heap allocated.
|
||||
|
||||
@raise Failure if the name is already taken
|
||||
@raise Invalid_argument if [weak] is true and no finalizer can be
|
||||
registered. *)
|
||||
|
||||
val unregister : t -> string -> unit
|
||||
(** Remove a stateful value *)
|
||||
|
||||
val add_list : t -> (string * State.wrap) list -> unit
|
||||
(** Register several handlers.
|
||||
@raise Failure if it meets an already registered handler *)
|
||||
|
||||
val to_list : t -> (string * State.wrap) list
|
||||
(** Currently registered objects *)
|
||||
|
||||
val random_id : unit -> string
|
||||
(** Fresh, random ID that can be used for registering temporary objects *)
|
||||
|
||||
val handle_request : t -> CamlGI.Cgi.Request.t -> unit
|
||||
(** Handle the incoming request, by routing to an appropriate
|
||||
object. *)
|
||||
end
|
||||
|
||||
(** {2 Main interface} *)
|
||||
|
||||
(* TODO: interface with {! LazyGraph}. A (string, html.t, string) graph
|
||||
maps naturally to URLs and simplifies routing. *)
|
||||
|
||||
val serve_state : ?sockfile:string -> ?sockaddr:Unix.sockaddr ->
|
||||
'a State.t -> unit
|
||||
(** Serve incoming requests using a single object.
|
||||
@param sockfile the unix file to use as a socket *)
|
||||
|
||||
val serve_router : ?sockfile:string -> ?sockaddr:Unix.sockaddr ->
|
||||
Router.t -> unit
|
||||
(** Shortcut. It calls {!CamlGI.Cgi.register_script} with a callback
|
||||
that forwards requests to the given Router.
|
||||
@param sockfile the unix file to use as a socket *)
|
||||
|
|
@ -29,27 +29,27 @@ From https://github.com/mjambon/mixtbl , thanks to him.
|
|||
Example:
|
||||
|
||||
{[
|
||||
let inj_int = Mixtbl.access () ;;
|
||||
let inj_int = CCMixtbl.access () ;;
|
||||
|
||||
let tbl = Mixtbl.create 10 ;;
|
||||
let tbl = CCMixtbl.create 10 ;;
|
||||
|
||||
OUnit.assert_equal None (Mixtbl.get ~inj:inj_int tbl "a");;
|
||||
OUnit.assert_equal None (CCMixtbl.get ~inj:inj_int tbl "a");;
|
||||
|
||||
Mixtbl.set inj_int tbl "a" 1;;
|
||||
CCMixtbl.set inj_int tbl "a" 1;;
|
||||
|
||||
OUnit.assert_equal (Some 1) (Mixtbl.get ~inj:inj_int tbl "a");;
|
||||
OUnit.assert_equal (Some 1) (CCMixtbl.get ~inj:inj_int tbl "a");;
|
||||
|
||||
let inj_string = Mixtbl.access () ;;
|
||||
let inj_string = CCMixtbl.access () ;;
|
||||
|
||||
Mixtbl.set inj_string tbl "b" "Hello";
|
||||
CCMixtbl.set inj_string tbl "b" "Hello";
|
||||
|
||||
OUnit.assert_equal (Some "Hello") (Mixtbl.get inj_string tbl "b");;
|
||||
OUnit.assert_equal None (Mixtbl.get inj_string tbl "a");;
|
||||
OUnit.assert_equal (Some 1) (Mixtbl.get inj_int tbl "a");;
|
||||
Mixtbl.set inj_string tbl "a" "Bye";;
|
||||
OUnit.assert_equal (Some "Hello") (CCMixtbl.get inj_string tbl "b");;
|
||||
OUnit.assert_equal None (CCMixtbl.get inj_string tbl "a");;
|
||||
OUnit.assert_equal (Some 1) (CCMixtbl.get inj_int tbl "a");;
|
||||
CCMixtbl.set inj_string tbl "a" "Bye";;
|
||||
|
||||
OUnit.assert_equal None (Mixtbl.get inj_int tbl "a");;
|
||||
OUnit.assert_equal (Some "Bye") (Mixtbl.get inj_string tbl "a");;
|
||||
OUnit.assert_equal None (CCMixtbl.get inj_int tbl "a");;
|
||||
OUnit.assert_equal (Some "Bye") (CCMixtbl.get inj_string tbl "a");;
|
||||
]}
|
||||
|
||||
@since 0.6 *)
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue