Commit 693c8315 authored by Eric Timmons's avatar Eric Timmons
Browse files

Add fast-http and dependencies

parent 5c8c33b2
......@@ -139,3 +139,15 @@
[submodule "ext/trivial-utf-8"]
path = ext/trivial-utf-8
url = https://gitlab.common-lisp.net/trivial-utf-8/trivial-utf-8.git
[submodule "ext/fast-http"]
path = ext/fast-http
url = https://github.com/fukamachi/fast-http.git
[submodule "ext/proc-parse"]
path = ext/proc-parse
url = https://github.com/fukamachi/proc-parse.git
[submodule "ext/xsubseq"]
path = ext/xsubseq
url = https://github.com/fukamachi/xsubseq.git
[submodule "ext/smart-buffer"]
path = ext/smart-buffer
url = https://github.com/fukamachi/smart-buffer.git
......@@ -22,11 +22,13 @@
(:static-file "cl-ppcre")
(:static-file "cl-reexport")
(:static-file "cl-sqlite")
(:static-file "cl-utilities")
(:static-file "clon")
(:static-file "closer-mop")
(:static-file "dissect")
(:static-file "drakma")
(:static-file "exit-hooks")
(:static-file "fast-http")
(:static-file "flexi-streams")
(:static-file "ironclad")
(:static-file "iterate")
......@@ -37,9 +39,11 @@
(:static-file "nibbles")
(:static-file "openssl")
(:static-file "optima")
(:static-file "proc-parse")
(:static-file "puri")
(:static-file "salza2")
(:static-file "sbcl")
(:static-file "smart-buffer")
(:static-file "split-sequence")
(:static-file "sxql")
(:static-file "trivial-features")
......@@ -48,5 +52,6 @@
(:static-file "trivial-utf-8")
(:static-file "unix-opts")
(:static-file "usocket")
(:static-file "uuid")))
(:static-file "uuid")
(:static-file "xsubseq")))
(:file "src/clpm-licenses/main")))
CL-UTILITIES Collection
=======================
On Cliki.net <http://www.cliki.net/Common%20Lisp%20Utilities>, there
is a collection of Common Lisp Utilities, things that everybody writes
since they're not part of the official standard. There are some very
useful things there; the only problems are that they aren't
implemented as well as you'd like (some aren't implemented at all) and
they aren't conveniently packaged and maintained. It takes quite a bit
of work to carefully implement utilities for common use, commented
and documented, with error checking placed everywhere some dumb user
might make a mistake.
The CLRFI process <http://clrfi.alu.org/> is a lot better thought out,
and will probably produce better standards than informal discussion on
a Wiki, but it has one problem: at the time of this writing, it's not
doing anything yet. Until the CLRFI process gets going, I think that a
high-quality collection of the informal standards on Cliki is a
valuable thing to have. It's here, and it's called cl-utilities.
The home page is <http://common-lisp.net/project/cl-utilities/>.
Documentation
-------------
Right now, documentation is at
<http://www.cliki.net/Common%20Lisp%20Utilities>. There are a few
differences, though:
* The READ-DELIMITED function takes :start and :end keyword args.
* A WITH-GENSYMS function is provided for compatibility.
* COPY-ARRAY is not called SHALLOW-COPY-ARRAY.
* The ONCE-ONLY macro is included.
Installation
------------
To install cl-utilities, you'll need to do one of two things:
* Download cl-utilities into a place where asdf can find it, then
load it via asdf. You will also need to get the split-sequence
package, which cl-utilities depends on.
-or-
* Use asdf-install: (asdf-install:install :cl-utilities)
Feedback
--------
The current maintainer is Peter Scott. If you have questions, bugs,
comments, or contributions, please send them to the cl-utilities-devel
mailing list, <cl-utilities-devel@common-lisp.net>.
License
-------
The code in cl-utilities is in the public domain. Do whatever you want
with it.
\ No newline at end of file
;; -*- Lisp -*-
(defpackage #:cl-utilities-system
(:use #:common-lisp #:asdf))
(in-package #:cl-utilities-system)
(defsystem cl-utilities
:author "Maintained by Peter Scott"
:components ((:file "package")
(:file "split-sequence" :depends-on ("package"))
(:file "extremum" :depends-on ("package"
"with-unique-names"
"once-only"))
(:file "read-delimited" :depends-on ("package"))
(:file "expt-mod" :depends-on ("package"))
(:file "with-unique-names" :depends-on ("package"))
(:file "collecting" :depends-on ("package"
"with-unique-names"
"compose"))
(:file "once-only" :depends-on ("package"))
(:file "rotate-byte" :depends-on ("package"))
(:file "copy-array" :depends-on ("package"))
(:file "compose" :depends-on ("package"))))
;; Sometimes we can accelerate byte rotation on SBCL by using the
;; SB-ROTATE-BYTE extension. This loads it.
#+sbcl
(eval-when (:compile-toplevel :load-toplevel :execute)
(handler-case (progn
(require :sb-rotate-byte)
(pushnew :sbcl-uses-sb-rotate-byte *features*))
(error () (delete :sbcl-uses-sb-rotate-byte *features*))))
\ No newline at end of file
;; Opinions differ on how a collection macro should work. There are
;; two major points for discussion: multiple collection variables and
;; implementation method.
;;
;; There are two main ways of implementing collection: sticking
;; successive elements onto the end of the list with tail-collection,
;; and using the PUSH/NREVERSE idiom. Tail-collection is usually
;; faster, except on CLISP, where PUSH/NREVERSE is a little faster.
;;
;; The COLLECTING macro only allows collection into one list, and you
;; can't nest them to get the same effect as multiple collection since
;; it always uses the COLLECT function. If you want to collect into
;; multiple lists, use the WITH-COLLECT macro.
(in-package :cl-utilities)
;; This should only be called inside of COLLECTING macros, but we
;; define it here to provide an informative error message and to make
;; it easier for SLIME (et al.) to get documentation for the COLLECT
;; function when it's used in the COLLECTING macro.
(defun collect (thing)
"Collect THING in the context established by the COLLECTING macro"
(error "Can't collect ~S outside the context of the COLLECTING macro"
thing))
(defmacro collecting (&body body)
"Collect things into a list forwards. Within the body of this macro,
the COLLECT function will collect its argument into the list returned
by COLLECTING."
(with-unique-names (collector tail)
`(let (,collector ,tail)
(labels ((collect (thing)
(if ,collector
(setf (cdr ,tail)
(setf ,tail (list thing)))
(setf ,collector
(setf ,tail (list thing))))))
,@body)
,collector)))
(defmacro with-collectors ((&rest collectors) &body body)
"Collect some things into lists forwards. The names in COLLECTORS
are defined as local functions which each collect into a separate
list. Returns as many values as there are collectors, in the order
they were given."
(%with-collectors-check-collectors collectors)
(let ((gensyms-alist (%with-collectors-gensyms-alist collectors)))
`(let ,(loop for collector in collectors
for tail = (cdr (assoc collector gensyms-alist))
nconc (list collector tail))
(labels ,(loop for collector in collectors
for tail = (cdr (assoc collector gensyms-alist))
collect `(,collector (thing)
(if ,collector
(setf (cdr ,tail)
(setf ,tail (list thing)))
(setf ,collector
(setf ,tail (list thing))))))
,@body)
(values ,@collectors))))
(defun %with-collectors-check-collectors (collectors)
"Check that all of the COLLECTORS are symbols. If not, raise an error."
(let ((bad-collector (find-if-not #'symbolp collectors)))
(when bad-collector
(error 'type-error
:datum bad-collector
:expected-type 'symbol))))
(defun %with-collectors-gensyms-alist (collectors)
"Return an alist mapping the symbols in COLLECTORS to gensyms"
(mapcar #'cons collectors
(mapcar (compose #'gensym
#'(lambda (x)
(format nil "~A-TAIL-" x)))
collectors)))
;; Some test code which would be too hard to move to the test suite.
#+nil (with-collectors (one-through-nine abc)
(mapcar #'abc '(a b c))
(dotimes (x 10)
(one-through-nine x)
(print one-through-nine))
(terpri) (terpri))
\ No newline at end of file
;; This version of COMPOSE can only handle functions which take one
;; value and return one value. There are other ways of writing
;; COMPOSE, but this is the most commonly used.
(in-package :cl-utilities)
;; This is really slow and conses a lot. Fortunately we can speed it
;; up immensely with a compiler macro.
(defun compose (&rest functions)
"Compose FUNCTIONS right-associatively, returning a function"
#'(lambda (x)
(reduce #'funcall functions
:initial-value x
:from-end t)))
;; Here's some benchmarking code that compares various methods of
;; doing the same thing. If the first method, using COMPOSE, is
;; notably slower than the rest, the compiler macro probably isn't
;; being run.
#+nil
(labels ((2* (x) (* 2 x)))
(macrolet ((repeat ((x) &body body)
(with-unique-names (counter)
`(dotimes (,counter ,x)
(declare (type (integer 0 ,x) ,counter)
(ignorable ,counter))
,@body))))
;; Make sure the compiler macro gets run
(declare (optimize (speed 3) (safety 0) (space 0) (debug 1)))
(time (repeat (30000000) (funcall (compose #'1+ #'2* #'1+) 6)))
(time (repeat (30000000) (funcall (lambda (x) (1+ (2* (1+ x)))) 6)))
(time (repeat (30000000)
(funcall (lambda (x)
(funcall #'1+ (funcall #'2* (funcall #'1+ x))))
6)))))
;; Converts calls to COMPOSE to lambda forms with everything written
;; out and some things written as direct function calls.
;; Example: (compose #'1+ #'2* #'1+) => (LAMBDA (X) (1+ (2* (1+ X))))
(define-compiler-macro compose (&rest functions)
(labels ((sharp-quoted-p (x)
(and (listp x)
(eql (first x) 'function)
(symbolp (second x)))))
`(lambda (x) ,(reduce #'(lambda (fun arg)
(if (sharp-quoted-p fun)
(list (second fun) arg)
(list 'funcall fun arg)))
functions
:initial-value 'x
:from-end t))))
\ No newline at end of file
(in-package :cl-utilities)
(defun copy-array (array &key (undisplace nil))
"Shallow copies the contents of any array into another array with
equivalent properties. If array is displaced, then this function will
normally create another displaced array with similar properties,
unless UNDISPLACE is non-NIL, in which case the contents of the array
will be copied into a completely new, not displaced, array."
(declare (type array array))
(let ((copy (%make-array-with-same-properties array undisplace)))
(unless (array-displacement copy)
(dotimes (n (array-total-size copy))
(setf (row-major-aref copy n) (row-major-aref array n))))
copy))
(defun %make-array-with-same-properties (array undisplace)
"Make an array with the same properties (size, adjustability, etc.)
as another array, optionally undisplacing the array."
(apply #'make-array
(list* (array-dimensions array)
:element-type (array-element-type array)
:adjustable (adjustable-array-p array)
:fill-pointer (when (array-has-fill-pointer-p array)
(fill-pointer array))
(multiple-value-bind (displacement offset)
(array-displacement array)
(when (and displacement (not undisplace))
(list :displaced-to displacement
:displaced-index-offset offset))))))
\ No newline at end of file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HEAD>
<TITLE>Macro COLLECTING, WITH-COLLECTORS</TITLE>
<LINK REL="stylesheet" HREF="style.css" type="text/css">
</HEAD>
<BODY>
<p><p><i>Macro</i> <b>COLLECTING</b></a></a> <p>
<p><b>Syntax:</b><p>
<p>
<p><b>collecting</b> <i>form*</i> => <i>result</i><p>
<p><b>with-collectors</b> <i>(collector*) form*</i> => <i>result</i>*<p>
<p>
<p><b>Arguments and Values:</b><p>
<p>
<i>forms</i>---an <a
href="http://www.lispworks.com/documentation/HyperSpec/Body/glo_i.html#implicit_progn">implicit
progn</a>.
<p><i>collector</i>---a symbol which will have a collection function bound to it.
<p><i>result</i>---a collected list.
<p>
<p><b>Description:</b><p>
<p>
<b>collecting</b> collects things into a list. Within the
body of this macro, the <b>collect</b> function will collect its
argument into <i>result</i>.
<p><b>with-collectors</b> collects some things into lists. The
<i>collector</i> names are defined as local functions which each
collect into a separate list. Returns as many values as there are
collectors, in the order they were given.
<p><b>Exceptional situations:</b><p>
<p>
<p>If the <i>collector</i> names are not all symbols, a
<b>type-error</b> will be signalled.
<p><b>Examples:</b>
<pre>
(collecting (dotimes (x 10) (collect x))) => (0 1 2 3 4 5 6 7 8 9)
(multiple-value-bind (a b)
(with-collectors (x y)
(x 1)
(y 2)
(x 3))
(append a b)) => (1 2 3)
</pre>
<p><p><b>Implementation notes:</b></p>
<p>Opinions differ on how a collection macro should work. There are
two major points for discussion: multiple collection variables and
implementation method.</b>
<p>There are two main ways of implementing collection: sticking
successive elements onto the end of the list with tail-collection, or
using the PUSH/NREVERSE idiom. Tail-collection is usually faster,
except on CLISP, where PUSH/NREVERSE is a little faster because it's
implemented in C which is always faster than Lisp bytecode.</p>
<p>The <b>collecting</b> macro only allows collection into one list,
and you can't nest them to get the same effect as multiple collection
since it always uses the <b>collect</b> function. If you want to
collect into multiple lists, use the <b>with-collect</b> macro.</p>
<p class="footer"><hr><a href="index.html">Manual Index</a></p>
</body></html>
\ No newline at end of file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HEAD>
<TITLE>Function COMPOSE</TITLE>
<LINK REL="stylesheet" HREF="style.css" type="text/css">
</HEAD>
<BODY>
<p><p><i>Function</i> <b>COMPOSE</b></p>
<p><p><b>Syntax:</b></p>
<p><p><b>compose</b> <i>function* <tt>=></tt> composite-function</i></p>
<p><p><b>Arguments and Values:</b></p>
<p><p><i>function</i>---a <i><a href="http://www.lispworks.com/documentation/HyperSpec/Body/glo_f.html#function_designator">function designator</a></i>.</p>
<p><i>composite-function</i>---a <i>function</i>.
<p><p><b>Description:</b></p>
<p>Composes its arguments into a single composite function. All its
arguments are assumed to designate functions which take one argument
and return one argument.
<p><tt>(funcall (compose f g) 42)</tt> is equivalent to <tt>(f (g
42))</tt>. Composition is right-associative.
<p><b>Examples:</b>
<pre>
;; Just to illustrate order of operations
(defun 2* (x) (* 2 x))
(funcall (compose #'1+ #'1+) 1) => 3
(funcall (compose '1+ '2*) 5) => 11
(funcall (compose #'1+ '2* '1+) 6) => 15
</pre>
<p><b>Notes:</b>
<p>If you're dealing with multiple arguments and return values, the
same concept can be used. Here is some code that could be useful:
<pre>
(defun mv-compose2 (f1 f2)
(lambda (&rest args)
(multiple-value-call f1 (apply f2 args))))
(defun mv-compose (&rest functions)
(if functions
(reduce #'mv-compose2 functions)
#'values))
</pre>
<p class="footer"><hr><a href="index.html">Manual Index</a></p>
</body></html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HEAD>
<TITLE>Function COPY-ARRAY</TITLE>
<LINK REL="stylesheet" HREF="style.css" type="text/css">
</HEAD>
<BODY>
<p><p><i>Function</i> <b>COPY-ARRAY</b></a></a> <p>
<p><b>Syntax:</b><p>
<p>
<p><b>copy-array</b> <i>array <tt>&key</tt> undisplace</i> => <i>new-array</i>
<p>
<p><b>Arguments and Values:</b><p>
<p>
<i>array</i>---an <i>array</i>. <p>
<i>undisplace</i>---a <i>generalized boolean</i>. The default is <i>false</i>.<p>
<i>new-array</i>---an <i>array</i></a>. <p>
<p>
<p><b>Description:</b><p>
<p>Shallow copies the contents of <i>array</i> into another array with
equivalent properties. If <i>array</i> is displaced, then this
function will normally create another displaced array with similar
properties, unless <i>undisplace</i> is <i>true</i>, in which case the
contents of <i>array</i> will be copied into a completely new, not
displaced, array.</p>
<p><p><b>Examples:</b></p>
<pre>
(copy-array #(1 2 3)) => #(1 2 3)
(let ((array #(1 2 3)))
(eq (copy-array array) array)) => NIL
</pre>
<p><p><b>Side Effects:</b> None.</p>
<p><p><b>Affected By:</b> None.</p>
<p class="footer"><hr><a href="index.html">Manual Index</a></p>
</body></html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HEAD>
<TITLE>Function EXPT-MOD</TITLE>
<LINK REL="stylesheet" HREF="style.css" type="text/css">
</HEAD>
<BODY>
<p><p><i>Function</i> <b>EXPT-MOD</b></a></a> <p>
<p><b>Syntax:</b><p>
<p><b>expt-mod</b> <i>n exponent divisor</i> => <i>result</i>
<p>
<p><b>Arguments and Values:</b><p>
<p>
<i>n</i>---a <i>number</i></a>. <p>
<i>exponent</i>---a <i>number</i></a>. <p>
<i>divisor</i>---a <i>number</i></a>. <p>
<i>result</i>---a <i>number</i></a>. <p>
<p>
<p><b>Description:</b><p>
<p>
<b>expt-mod</b> returns <i>n</i> raised to the <i>exponent</i> power,
modulo <i>divisor</i>. <tt>(expt-mod n exponent divisor)</tt> is
equivalent to <tt>(mod (expt n exponent) divisor)</tt>.
<p>
<p><b>Exceptional situations:</b><p>
<p>
<p>The exceptional situations are the same as those for <tt>(mod (expt
n exponent) divisor)</tt>.
<p><p><b>Notes:</b></p>
<p>One might wonder why we shouldn't simply write <tt>(mod (expt n
exponent) divisor)</tt>. This function exists because the na&iuml;ve
way of evaluating <tt>(mod (expt n exponent) divisor)</tt> produces a
gigantic intermediate result, which kills performance in applications
which use this operation heavily. The operation can be done much more
efficiently. Usually the compiler does this optimization
automatically, producing very fast code. However, we can't
<i>depend</i> on this behavior if we want to produce code that is
guaranteed not to perform abysmally on some Lisp implementations.
<p>Therefore cl-utilities provides a standard interface to this
composite operation which uses mediocre code by default. Specific
implementations can usually do much better, but some do much
worse. We can get the best of both by simply using the same interface
and doing read-time conditionalization within cl-utilities to get
better performance on compilers like SBCL and Allegro CL which
optimize this operation.
<p class="footer"><hr><a href="index.html">Manual Index</a></p>
</body></html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HEAD>
<TITLE>Function EXTREMUM, EXTREMA, N-MOST-EXTREME</TITLE>
<LINK REL="stylesheet" HREF="style.css" type="text/css">
</HEAD>
<BODY>
<p><p><i>Function</i> <b>EXTREMUM, EXTREMA, N-MOST-EXTREME</b></a></a> <p>
<p><b>Syntax:</b><p>
<p>
<p><b>extremum</b> <i>sequence predicate <tt>&key</tt> key (start 0) end</i> => <i>morally-smallest-element</i><p>
<p><b>extrema</b> <i>sequence predicate <tt>&key</tt> key (start 0) end</i> => <i>morally-smallest-elements</i><p>
<p><b>n-most-extreme</b> <i>n sequence predicate <tt>&key</tt> key (start 0) end</i> => <i>n-smallest-elements</i><p>
<p>
<p><b>Arguments and Values:</b><p>
<p>
<i>sequence</i>---a <i>proper sequence</i></a>. <p>
<i>predicate</i>---a <i>designator</i> for a <i>function</i> of two
arguments that returns a <i>generalized boolean</i>. <p>
<i>key</i>---a <i>designator</i> for a <i>function</i> of one
argument, or <b>nil</b>. <p>
<i>start, end</i>---bounding index designators of <i>sequence</i>. The
defaults for start and end are 0 and <b>nil</b>, respectively.<p>
<i>morally-smallest-element</i>---the element of <i>sequence</i> that
would appear first if the sequence were ordered according to <a
class="hyperspec" href ="
http://www.lispworks.com/documentation/HyperSpec/Body/fun_sortcm_stable-sort.html"><b>sort</b></a>
using <i>predicate</i> and <i>key</i>
<p><i>morally-smallest-elements</i>---the identical elements of
<i>sequence</i> that would appear first if the sequence were ordered
according to <a class="hyperspec" href ="
http://www.lispworks.com/documentation/HyperSpec/Body/fun_sortcm_stable-sort.html"><b>sort</b></a>
using <i>predicate</i> and <i>key</i>. If <i>predicate</i> states that
neither of two objects is before the other, they are considered
identical.
<i>n</i>---a positive integer<p>
<i>n-smallest-elements</i>---the <i>n</i> elements of <i>sequence</i> that
would appear first if the sequence were ordered according to <a
class="hyperspec" href ="