<commit_before>(in-ns 'compojure)
(clojure/refer 'clojure)
(import '(javax.servlet.http HttpServletRequest HttpServletResponse))

(defn includes?
  "Returns true if x is contained in coll, else false."
  [x coll]
  (some (partial = x) coll))

(defn re-escape
  "Escape all special regex chars in a string s."
  [s]
  (let [chars  "\\.*+|?()[]{}$^"
        escape #(if (includes? % chars) [\\ %] [%])]
    (apply str (mapcat escape s))))

(def symbol-regex  (re-pattern ":([a-z_]+)"))

(defn re-find-all
  "Repeat re-find for matcher m until nil, and return the seq of results."
  [m]
  (doall (take-while identity
    (map re-find (repeat m)))))

(defn parse-route
  "Turn a route string into a regex and seq of symbols."
  [route]
  (let [segment  "([^/.,;?]+)"
        matcher  (re-matcher symbol-regex (re-escape route))
        symbols  (re-find-all matcher)
        regex    (. matcher (replaceAll segment))]
    [(re-pattern regex) (map second symbols)]))

(defn match-route 
  "Match a path against a parsed route. Returns a map of keywords and their
   matching path values."
  [[regex symbols] path]
  (let [matcher (re-matcher regex path)]
    (if (. matcher (matches))
      (apply hash-map
        (interleave (map keyword symbols)
                    (rest (re-groups matcher)))))))

(defn update-response!
  "Destructively update a HttpServletResponse via a Clojure datatype.
     * FixNum        - updates status code
     * map           - updates headers
     * string or seq - updates body
   Additionally, multiple updates can be chained through a vector.

   e.g (update-response! \"Foo\")       ; write 'Foo' to response body
       (update-response! [200 \"Bar\"]) ; set status to 200, and write 'Bar'"
  [#^HttpServletResponse response change]
  (cond 
    (string? change)
      (.. response (getWriter) (print change))
    (seq? change)
      (let [writer (. response (getWriter))]
        (doseq c change
          (. writer (print c))))
    (instance? clojure.lang.FixNum change)
      (. response (setStatus change))
    (map? change)
      (doseq [k v] change
        (. response (setHeader k v)))
    (vector? change)
      (doseq c change
        (update-response! response c))))

(def *resources* {})

(defn add-resource
  "Add a resource to the global *resources* map. A resource is a HTTP
   method keyword, a route, and a body to be evaluated in order to generate
   a response.
   e.g. (add-resource :GET \"/welcome/:name\"
          '(str \"Hello \" (path :name)))"
  [method route & body]
  (def *resources*
    (assoc *resources* method
      (cons [(parse-route route) body]
        (*resources* method)))))

(defn find-resource
  "Find the first resource that matches the HttpServletRequest"
  [#^HttpServletRequest request]
  (let [method    (. request (getMethod))
        path      (. request (getPathInfo))
        resources (*resources* (keyword method))
        matches?  (fn [[route body]]
                    (if (match-route route path) body))]
    (some matches? resources)))<commit_msg>Removed *resources* hashmap - premature optimisation<commit_after>(in-ns 'compojure)
(clojure/refer 'clojure)
(import '(javax.servlet.http HttpServletRequest HttpServletResponse))

(defn includes?
  "Returns true if x is contained in coll, else false."
  [x coll]
  (some (partial = x) coll))

(defn re-escape
  "Escape all special regex chars in a string s."
  [s]
  (let [chars  "\\.*+|?()[]{}$^"
        escape #(if (includes? % chars) [\\ %] [%])]
    (apply str (mapcat escape s))))

(def symbol-regex  (re-pattern ":([a-z_]+)"))

(defn re-find-all
  "Repeat re-find for matcher m until nil, and return the seq of results."
  [m]
  (doall (take-while identity
    (map re-find (repeat m)))))

(defn parse-route
  "Turn a route string into a regex and seq of symbols."
  [route]
  (let [segment  "([^/.,;?]+)"
        matcher  (re-matcher symbol-regex (re-escape route))
        symbols  (re-find-all matcher)
        regex    (. matcher (replaceAll segment))]
    [(re-pattern regex) (map second symbols)]))

(defn match-route 
  "Match a path against a parsed route. Returns a map of keywords and their
  matching path values."
  [[regex symbols] path]
  (let [matcher (re-matcher regex path)]
    (if (. matcher (matches))
      (apply hash-map
        (interleave (map keyword symbols)
                    (rest (re-groups matcher)))))))

(defn update-response!
  "Destructively update a HttpServletResponse via a Clojure datatype.
     * FixNum        - updates status code
     * map           - updates headers
     * string or seq - updates body
  Additionally, multiple updates can be chained through a vector.

  e.g (update-response! \"Foo\")       ; write 'Foo' to response body
      (update-response! [200 \"Bar\"]) ; set status to 200, and write 'Bar'"
  [#^HttpServletResponse response change]
  (cond 
    (string? change)
      (.. response (getWriter) (print change))
    (seq? change)
      (let [writer (. response (getWriter))]
        (doseq c change
          (. writer (print c))))
    (instance? clojure.lang.FixNum change)
      (. response (setStatus change))
    (map? change)
      (doseq [k v] change
        (. response (setHeader k v)))
    (vector? change)
      (doseq c change
        (update-response! response c))))

(def #^{:doc
  "A global list of all registered resources. A resource is a vector
  consisting of a HTTP method, a parsed route, and a list of evaluatable
  actions.
  e.g.
  [\"GET\" (parse-route \"/welcome/:name\")
   '((str \"Hello \" (path :name))]"}
  *resources* '())

(defn add-resource
  "Add a resource to the global *resources*."
  [method route & body]
  (def *resources*
    (cons [method (parse-route route) body] *resources*)))

(defn find-resource
  "Find the first resource that matches the HttpServletRequest"
  [#^HttpServletRequest request]
  (let [method    (. request (getMethod))
        path      (. request (getPathInfo))
        matches?  (fn [[meth route body]]
                    (if (and (= meth method) (match-route route path))
                       body))]
    (some matches? *resources*)))
{'fraction_non_alphanumeric': 0.1377450980392157, 'fraction_numerical': 0.00196078431372549, 'mean_word_length': 2.718712029161604, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7275362', 'n_tokens_mistral': 1944, 'n_tokens_neox': 1891, 'n_words': 671}