Commits

Karsten Schmidt committed 5dc24b8

flow: Created branch 'release/0.1.1'.

  • Participants
  • Parent commits 7bc6b6c
  • Branches release/0.1.1

Comments (0)

Files changed (4)

-(defproject com.postspectacular/structgen "0.1.0"
+(defproject com.postspectacular/structgen "0.1.1"
   :description "Interop library for working with native C structs and binary formats in general."
   :url "http://hg.postspectacular.com/structgen"
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"
             :distribution :repo}
   :dependencies [[org.clojure/clojure "1.4.0"]
+                 [org.clojure/tools.namespace "0.2.1"]
                  [gloss "0.2.1"]
                  [net.cgrand/parsley "0.9.1"]])

src/clojure/data/dependency.clj

-(ns clojure.data.dependency
-  "Bidirectional graphs of dependencies and dependent objects."
-  ^{:author "Stuart Sierra"
-    :url "https://github.com/stuartsierra/data.dependency"}
-  (:use [clojure.set :only (union)]))
-
-(defprotocol DependencyGraph
-  (immediate-dependencies [graph key]
-    "Returns the set of immediate dependencies of key.")
-  (immediate-dependents [graph key]
-    "Returns the set of immediate dependents of key.")
-  (transitive-dependencies [graph key]
-    "Returns the set of all things which key depends on, directly or
-    transitively.")
-  (transitive-dependents [graph key]
-    "Returns the set of all things which depend upon x, directly or
-    transitively."))
-
-(defprotocol DependencyGraphUpdate
-  (depend [graph key dep]
-    "Returns a new graph with a dependency from key to dep. Forbids
-    circular dependencies.")
-  (remove-all [graph key]
-    "Returns a new dependency graph with all references to key removed.")
-  (remove-key [graph key]
-    "Removes the key from the dependency graph without removing it as a
-    dependency of other keys."))
-
-(defn- remove-from-map [amap x]
-  (reduce (fn [m [k vs]]
-	    (assoc m k (disj vs x)))
-	  {} (dissoc amap x)))
-
-(defn- transitive
-  "Recursively expands the set of dependency relationships starting
-  at (get m x)"
-  [m x]
-  (reduce (fn [s k]
-	    (union s (transitive m k)))
-	  (get m x) (get m x)))
-
-(declare depends?)
-
-(deftype MapDependencyGraph [dependencies dependents]
-  DependencyGraph
-  (immediate-dependencies [graph key]
-    (get dependencies key))
-  (immediate-dependents [graph key]
-    (get dependents key))
-  (transitive-dependencies [graph key]
-    (transitive dependencies key))
-  (transitive-dependents [graph key]
-    (transitive dependents key))
-  DependencyGraphUpdate
-  (depend [graph key dep]
-    (when (depends? graph dep key)
-      (throw (Exception.
-              (str "Circular dependency between "
-                   (pr-str key) " and " (pr-str dep)))))
-    (MapDependencyGraph.
-     (update-in dependencies [key] union #{dep})
-     (update-in dependents [dep] union #{key})))
-  (remove-all [graph key]
-    (MapDependencyGraph.
-     (remove-from-map dependencies key)
-     (remove-from-map dependents key)))
-  (remove-key [graph key]
-    (MapDependencyGraph.
-     (dissoc dependencies key)
-     dependents)))
-
-(defn graph "Returns a new, empty, dependency graph." []
-  (->MapDependencyGraph {} {}))
-
-(defn depends?
-  "True if x is directly or transitively dependent on y."
-  [graph x y]
-  (contains? (transitive-dependencies graph x) y))
-
-(defn dependent?
-  "True if y is a dependent of x."
-  [graph x y]
-  (contains? (transitive-dependents graph x) y))
-
-(defn topo-comparator
-  "Returns a comparator which produces a topographical sort based on
-  the dependencies in graph."
-  [graph]
-  (comparator (partial dependent? graph)))
-
-(defn topo-sort
-  "Returns a topographically-sorted sequence of the items in coll
-  using dependencies in graph."  
-  [graph coll]
-  (sort (topo-comparator graph) coll))
-
-(defn topo-sort-by
-  "Returns a topographically-sorted sequence of the items in coll by
-  comparing (keyfn item) using dependencies in graph."
-  [graph keyfn coll]
-  (sort-by keyfn (topo-comparator graph) coll))
-
-(comment
-  ;; example usage: building a graph like:
-  ;;
-  ;;     :a -------- :b
-  ;;       \          \
-  ;;        \          \
-  ;;         `-------- :c ---- :d
-  ;;
-  (def g (-> (graph)
-             (depend :b :a)
-             (depend :c :b)
-             (depend :c :a)
-             (depend :d :c)))
-
-  (transitive-dependencies g :d)
-  ;;=> #{:a :c :b}
-
-  (topo-sort g [:d :a :c :b])
-  ;;=> (:a :b :c :d)
-  )

src/structgen/core.clj

 (ns structgen.core
   "Utilities to seamlessly work with native C structs.
-  Provides extensible struct generators with customizable
-  alignment for converting between Clojure maps and
+  Provides extensible struct generators and customizable
+  alignment logic for converting between Clojure maps and
   byte buffers. Supports nested structs, arrays, custom C
   primitives (e.g as used by OpenCL) and endianess.
   Can generate C source from Clojure defined structs."
     [gloss
       [core :as gc :only [compile-frame ordered-map sizeof]]
       [io :as gio :only [encode decode]]]
-    [clojure.data.dependency :as dep]))
+    [clojure.tools.namespace.dependency :as dep]))
 
 (defprotocol StructElement
   "Defines common functionality for primitives, primitive vectors,
     "Builds a dependency graph and generates C source for the typedef of
     this struct and all required dependencies (in correct order)."))
 
+;; # Helper fns
+
+(defn deep-merge-with
+  "Like merge-with, but merges maps recursively, applying the given fn
+  only when there's a non-map at a particular level.
+
+      (deep-merge-with +
+        {:a {:b {:c 1 :d {:x 1 :y 2}} :e 3} :f 4}
+        {:a {:b {:c 2 :d {:z 9} :z 3} :e 100}})
+      => {:a {:b {:z 3, :c 3, :d {:z 9, :x 1, :y 2}}, :e 103}, :f 4}"
+  ^{:author "Chris Houser"}
+  [f & maps]
+  (apply
+    (fn m [& maps]
+      (if (every? map? maps)
+        (apply merge-with m maps)
+        (apply f maps)))
+    maps))
+
+(defn deep-select-keys
+  "Recursively selects only keys from map `m` matching the given struct spec.
+  This function is used internally by `decode` to exclude any alignment keys."
+  [m struct]
+  (reduce
+    (fn [m [k v]]
+      (if-let [ks (k (struct-spec struct))]
+        (assoc m k
+          (cond
+            (map? v)
+              (deep-select-keys v ks)
+            (and (sequential? v) (not (primitive? ks)))
+              (map #(deep-select-keys % (element-type ks)) v)
+            :default v))
+        m))
+    {} m))
+
+(defn merge-with-template
+  [tpl data]
+  (cond
+    (sequential? tpl)
+      (let [ct (count tpl) cd (count data)]
+        (if (every? map? [(first tpl) (first data)])
+          (map (fn [a b] (deep-merge-with merge-with-template a b))
+               tpl (concat (take ct data) (drop cd tpl)))
+          (if (< cd ct)
+            (concat data (drop cd tpl))
+            (take ct data))))
+    (nil? data) tpl
+    :default data))
+
 (defn ceil-multiple-of
   "Rounds up `b` to a multiple of `a`."
   [a b]
   `(binding [*config* (merge *config* ~config)]
      (do ~@body)))
 
+;; # C primitive datatype handling
+
 (defn primitive*
   "Returns a `StructElement` implementation for the given primitive type description:
 
       cname - C type name
       type - gloss codec type
-      size - size in bytes" 
+      size - size in bytes"
   [cname type size]
   (reify
     StructElement
   "Returns a `StructElement` implementation for the given vector primitive type description.
   E.g. OpenCL extends C with vector prims like `float4` which technically are like arrays,
   but differ in their C declarations:
-  
+
       float x[4]; // 4-element C array
       float4 x; // float4 primitive
 
       (template [this] (template this false))
       (template [this all?] (vec (repeat len (template e all?)))))))
 
+;; # Type registration
+
 (defn make-registry
   "Builds a vanilla type registry populated only with standard C
   and OpenCL primitive types."
   registers a number of structs for the given specs.
   Throws IllegalArgumentException for duplicate IDs.
   Returns the last type registered.
-  
+
   Each spec is a vector of: `[typename & fields]`
 
       ; declare a primitive OpenCL type
       (dosync (alter *registry* assoc id type)))
     type))
 
-(defn deep-merge-with
-  "Like merge-with, but merges maps recursively, applying the given fn
-  only when there's a non-map at a particular level.
-
-      (deep-merge-with +
-        {:a {:b {:c 1 :d {:x 1 :y 2}} :e 3} :f 4}
-        {:a {:b {:c 2 :d {:z 9} :z 3} :e 100}})
-      => {:a {:b {:z 3, :c 3, :d {:z 9, :x 1, :y 2}}, :e 103}, :f 4}"
-  ^{:author "Chris Houser"}
-  [f & maps]
-  (apply
-    (fn m [& maps]
-      (if (every? map? maps)
-        (apply merge-with m maps)
-        (apply f maps)))
-    maps))
-
-(defn deep-select-keys
-  "Recursively selects only keys from map `m` matching the given struct spec.
-  This function is used internally by `decode` to exclude any alignment keys."
-  [m struct]
-  (reduce
-    (fn [m [k v]]
-      (if-let [ks (k (struct-spec struct))]
-        (assoc m k 
-          (cond
-            (map? v)
-              (deep-select-keys v ks)
-            (and (sequential? v) (not (primitive? ks)))
-              (map #(deep-select-keys % (element-type ks)) v)
-            :default v))
-        m))
-    {} m))
-
-(defn merge-with-template
-  [tpl data]
-  (cond
-    (sequential? tpl)
-      (let [ct (count tpl) cd (count data)]
-        (if (every? map? [(first tpl) (first data)])
-          (map (fn [a b] (deep-merge-with merge-with-template a b))
-               tpl (concat (take ct data) (drop cd tpl)))
-          (if (< cd ct)
-            (concat data (drop cd tpl))
-            (take ct data))))
-    (nil? data) tpl
-    :default data))
+;; # Struct generation
 
 (defn build-align-spec*
   [len]
   (into {}
     (when (pos? len)
-      {:gid (keyword (gensym "_align__"))
+      {:gid (keyword (gensym "sg_align__"))
        :gcode (gc/compile-frame (repeat len :byte))
        :gdata (vec (repeat len 0))})))
 
              (throw (IllegalArgumentException. (str "unknown type " t)))))
          [[] 0 0] fields)
        block-fill (- (ceil-multiple-of stride total) total)]
-    ;(prn (ceil-multiple-of stride offset) offset total block-fill)
     (if (pos? block-fill)
       (concat spec [(build-align-spec* block-fill)])
       spec)))
       (gen-source [this]
         (let [g (dependencies this)
               deps (dep/transitive-dependencies g this)
-              sorted-deps (vec (dep/topo-sort g (vec (into #{this} deps))))]
+              sorted-deps (vec (dep/topo-sort g))
+              sorted-deps (if (seq sorted-deps) sorted-deps [this])]
           (apply str (header) (map gen-source* sorted-deps))))
       (struct-spec [this] spec-map))))

src/structgen/parser.clj

 (ns structgen.parser
+  "Basic C struct/typedef parser functions."
+  ^{:author "Karsten Schmidt"}
   (:require
   	[net.cgrand.parsley :as p :only [parser]]
   	[clojure.string :as string :only [replace]]))
 
 (defn preprocess
   ([src & {:as userdefs}]
-    (prn userdefs)
     (let [defines (re-seq c-define src)]
       (reduce
         (fn[s [o d r]]