]> gitweb.factorcode.org Git - factor.git/blob - basis/windows/com/wrapper/wrapper.factor
Delete empty unit tests files, remove 1- and 1+, reorder IN: lines in a lot of places...
[factor.git] / basis / windows / com / wrapper / wrapper.factor
1 USING: alien alien.c-types alien.accessors windows.com.syntax
2 init windows.com.syntax.private windows.com continuations kernel
3 namespaces windows.ole32 libc vocabs assocs accessors arrays
4 sequences quotations combinators math words compiler.units
5 destructors fry math.parser generalizations sets
6 specialized-arrays.alien specialized-arrays.direct.alien ;
7 IN: windows.com.wrapper
8
9 TUPLE: com-wrapper callbacks vtbls disposed ;
10
11 <PRIVATE
12
13 SYMBOL: +wrapped-objects+
14 +wrapped-objects+ get-global
15 [ H{ } +wrapped-objects+ set-global ]
16 unless
17
18 SYMBOL: +live-wrappers+
19 +live-wrappers+ get-global
20 [ V{ } +live-wrappers+ set-global ]
21 unless
22
23 SYMBOL: +vtbl-counter+
24 +vtbl-counter+ get-global
25 [ 0 +vtbl-counter+ set-global ]
26 unless
27
28 "windows.com.wrapper.callbacks" create-vocab drop
29
30 : (next-vtbl-counter) ( -- n )
31     +vtbl-counter+ [ 1 + dup ] change ;
32
33 : com-unwrap ( wrapped -- object )
34     +wrapped-objects+ get-global at*
35     [ "invalid COM wrapping pointer" throw ] unless ;
36
37 : (free-wrapped-object) ( wrapped -- )
38     [ +wrapped-objects+ get-global delete-at ] keep
39     free ;
40
41 : (query-interface-cases) ( interfaces -- cases )
42     [
43         [ find-com-interface-definition family-tree [ iid>> ] map ] dip
44         1quotation [ 2array ] curry map
45     ] map-index concat
46     [ drop f ] suffix ;
47
48 : (make-query-interface) ( interfaces -- quot )
49     (query-interface-cases) 
50     '[
51         swap 16 memory>byte-array
52         _ case
53         [
54             "void*" heap-size * rot <displaced-alien> com-add-ref
55             swap 0 set-alien-cell S_OK
56         ] [ nip f swap 0 set-alien-cell E_NOINTERFACE ] if*
57     ] ;
58
59 : (make-add-ref) ( interfaces -- quot )
60     length "void*" heap-size * '[
61         _
62         [ alien-unsigned-4 1 + dup ]
63         [ set-alien-unsigned-4 ]
64         2bi
65     ] ;
66
67 : (make-release) ( interfaces -- quot )
68     length "void*" heap-size * '[
69         _
70         [ drop ]
71         [ alien-unsigned-4 1 - dup ]
72         [ set-alien-unsigned-4 ]
73         2tri
74         dup 0 = [ swap (free-wrapped-object) ] [ nip ] if
75     ] ;
76
77 : (make-iunknown-methods) ( interfaces -- quots )
78     [ (make-query-interface) ]
79     [ (make-add-ref) ]
80     [ (make-release) ] tri
81     3array ;
82     
83 : (thunk) ( n -- quot )
84     dup 0 =
85     [ drop [ ] ]
86     [ "void*" heap-size neg * '[ _ swap <displaced-alien> ] ]
87     if ;
88
89 : (thunked-quots) ( quots iunknown-methods thunk -- {thunk,quot}s )
90     [ '[ @ com-unwrap ] [ swap 2array ] curry map ]
91     [                   [ swap 2array ] curry map ] bi-curry bi*
92     prepend ;
93
94 : compile-alien-callback ( word return parameters abi quot -- word )
95     '[ _ _ _ _ alien-callback ]
96     [ [ (( -- alien )) define-declared ] pick [ call ] dip ]
97     with-compilation-unit ;
98
99 : (callback-word) ( function-name interface-name counter -- word )
100     [ "::" rot 3append "-callback-" ] dip number>string 3append
101     "windows.com.wrapper.callbacks" create ;
102
103 : (finish-thunk) ( param-count thunk quot -- thunked-quot )
104     [ [ drop [ ] ] [ swap 1 - '[ _ _ ndip ] ] if-empty ]
105     dip compose ;
106
107 : (make-interface-callbacks) ( interface-name quots iunknown-methods n -- words )
108     (thunk) (thunked-quots)
109     swap [ find-com-interface-definition family-tree-functions ]
110     keep (next-vtbl-counter) '[
111         swap [
112             [ name>> _ _ (callback-word) ]
113             [ return>> ] [
114                 parameters>>
115                 [ [ first ] map ]
116                 [ length ] bi
117             ] tri
118         ] [
119             first2 (finish-thunk)
120         ] bi*
121         "stdcall" swap compile-alien-callback
122     ] 2map ;
123
124 : (make-callbacks) ( implementations -- sequence )
125     dup [ first ] map (make-iunknown-methods)
126     [ [ first2 ] 2dip swap (make-interface-callbacks) ]
127     curry map-index ;
128
129 : (malloc-wrapped-object) ( wrapper -- wrapped-object )
130     vtbls>> length "void*" heap-size *
131     [ "ulong" heap-size + malloc ] keep
132     [ [ 1 ] 2dip set-alien-unsigned-4 ] [ drop ] 2bi ;
133
134 : (callbacks>vtbl) ( callbacks -- vtbl )
135     [ execute( -- callback ) ] void*-array{ } map-as malloc-byte-array ;
136 : (callbacks>vtbls) ( callbacks -- vtbls )
137     [ (callbacks>vtbl) ] map ;
138
139 : (allocate-wrapper) ( wrapper -- )
140     dup callbacks>> (callbacks>vtbls) >>vtbls
141     f >>disposed drop ;
142
143 : (init-hook) ( -- )
144     +live-wrappers+ get-global [ (allocate-wrapper) ] each
145     H{ } +wrapped-objects+ set-global ;
146
147 [ (init-hook) ] "windows.com.wrapper" add-init-hook
148
149 PRIVATE>
150
151 : allocate-wrapper ( wrapper -- )
152     [ (allocate-wrapper) ]
153     [ +live-wrappers+ get adjoin ] bi ;
154
155 : <com-wrapper> ( implementations -- wrapper )
156     (make-callbacks) f f com-wrapper boa
157     dup allocate-wrapper ;
158
159 M: com-wrapper dispose*
160     [ [ free ] each f ] change-vtbls
161     +live-wrappers+ get-global delete ;
162
163 : com-wrap ( object wrapper -- wrapped-object )
164     [ vtbls>> ] [ (malloc-wrapped-object) ] bi
165     [ over length <direct-void*-array> 0 swap copy ] keep
166     [ +wrapped-objects+ get-global set-at ] keep ;