1 ! Copyright (C) 2011 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien alien.accessors alien.c-types alien.data
4 classes.struct.private combinators compiler.units endian fry
5 generalizations kernel macros math namespaces sequences words
7 QUALIFIED-WITH: alien.c-types ac
10 ERROR: invalid-signed-conversion n ;
12 : convert-signed-quot ( n -- quot )
14 { 1 [ [ char <ref> char deref ] ] }
15 { 2 [ [ ac:short <ref> ac:short deref ] ] }
16 { 4 [ [ int <ref> int deref ] ] }
17 { 8 [ [ longlong <ref> longlong deref ] ] }
18 [ invalid-signed-conversion ]
23 : byte-mask ( #bits-shift -- mask )
24 [ HEX: ff ] dip shift ; foldable
28 MACRO: byte-reverse ( n signed? -- quot )
33 [ 1 + - -8 * ] [ nip 8 * ] 2bi
34 [ + ] [ nip byte-mask ] 2bi
37 ] [ 1 - [ bitor ] n*quot ] bi
39 [ convert-signed-quot ] [ drop [ ] ] if
43 SYMBOLS: le8 be8 ule8 ube8
44 ule16 ule32 ule64 ube16 ube32 ube64
45 le16 le32 le64 be16 be32 be64 ;
47 : endian-c-type? ( symbol -- ? )
49 le8 be8 ule8 ube8 ule16 ule32 ule64
50 ube16 ube32 ube64 le16 le32 le64 be16 be32 be64
53 ERROR: unknown-endian-c-type symbol ;
55 : endian-c-type>c-type-symbol ( symbol -- symbol' )
57 { [ dup { ule16 ube16 } member? ] [ drop ushort ] }
58 { [ dup { le16 be16 } member? ] [ drop ac:short ] }
59 { [ dup { ule32 ube32 } member? ] [ drop uint ] }
60 { [ dup { le32 be32 } member? ] [ drop int ] }
61 { [ dup { ule64 ube64 } member? ] [ drop ulonglong ] }
62 { [ dup { le64 be64 } member? ] [ drop longlong ] }
63 [ unknown-endian-c-type ]
66 : change-c-type-accessors ( n ? c-type -- c-type' )
67 endian-c-type>c-type-symbol "c-type" word-prop clone
69 [ '[ [ _ _ byte-reverse ] compose ] change-getter drop ]
70 [ '[ [ [ _ _ byte-reverse ] 2dip ] prepose ] change-setter ] 3bi ;
72 : typedef-endian ( n ? c-type endian -- )
73 native-endianness get = [
74 2nip [ endian-c-type>c-type-symbol ] keep typedef
76 [ change-c-type-accessors ] keep typedef
79 : typedef-le ( n ? c-type -- ) little-endian typedef-endian ;
80 : typedef-be ( n ? c-type -- ) big-endian typedef-endian ;
85 \ uchar \ ule8 typedef
86 \ uchar \ ube8 typedef
87 2 f \ ule16 typedef-le
88 2 f \ ube16 typedef-be
91 4 f \ ule32 typedef-le
92 4 f \ ube32 typedef-be
95 8 f \ ule64 typedef-le
96 8 f \ ube64 typedef-be
99 ] with-compilation-unit
102 : pair>c-type ( pair -- c-type )
103 [ native-endianness get big-endian = ] dip first2 ? ;
105 ! endian is desired endian type. if we match endianness, return the c type
106 ! otherwise return the opposite of our endianness
107 : endian-slot ( endian c-type pair -- endian-slot )
108 [ native-endianness get = ] 2dip rot [ drop ] [ nip pair>c-type ] if ;
110 ERROR: unsupported-endian-type endian slot ;
112 : slot>endian-slot ( endian slot -- endian-slot )
114 first2 [ slot>endian-slot ] dip 2array
117 { [ dup char = ] [ 2drop char ] }
118 { [ dup uchar = ] [ 2drop uchar ] }
119 { [ dup ac:short = ] [ { le16 be16 } endian-slot ] }
120 { [ dup ushort = ] [ { ule16 ube16 } endian-slot ] }
121 { [ dup int = ] [ { le32 be32 } endian-slot ] }
122 { [ dup uint = ] [ { ule32 ube32 } endian-slot ] }
123 { [ dup longlong = ] [ { le64 be64 } endian-slot ] }
124 { [ dup ulonglong = ] [ { ule64 ube64 } endian-slot ] }
125 { [ dup endian-c-type? ] [ nip ] }
126 [ unsupported-endian-type ]
130 : set-endian-slots ( endian slots -- slot-specs )
131 [ [ slot>endian-slot ] change-type ] with map ;
133 : define-endian-struct-class ( class slots endian -- )
134 swap make-slots set-endian-slots
135 [ compute-struct-offsets ] [ struct-alignment ]
136 (define-struct-class) ;
138 : define-endian-packed-struct-class ( class slots endian -- )
139 swap make-packed-slots set-endian-slots
140 [ compute-struct-offsets ] [ drop 1 ]
141 (define-struct-class) ;
144 parse-struct-definition
145 little-endian define-endian-struct-class ;
148 parse-struct-definition
149 big-endian define-endian-struct-class ;
151 SYNTAX: LE-PACKED-STRUCT:
152 parse-struct-definition
153 little-endian define-endian-packed-struct-class ;
155 SYNTAX: BE-PACKED-STRUCT:
156 parse-struct-definition
157 big-endian define-endian-packed-struct-class ;