]> gitweb.factorcode.org Git - factor.git/blob - basis/pack/pack.factor
Fixes #2966
[factor.git] / basis / pack / pack.factor
1 ! Copyright (C) 2009 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien.c-types ascii assocs combinators combinators.smart
4 endian io kernel math math.statistics math.vectors sequences
5 strings ;
6 IN: pack
7
8 GENERIC: >n-byte-array ( obj n -- byte-array )
9
10 M: integer >n-byte-array >endian ;
11
12 ! for doing native, platform-dependent sized values
13 M: object >n-byte-array heap-size >n-byte-array ;
14
15 : s8>byte-array ( n -- byte-array ) 1 >n-byte-array ;
16 : u8>byte-array ( n -- byte-array ) 1 >n-byte-array ;
17 : s16>byte-array ( n -- byte-array ) 2 >n-byte-array ;
18 : u16>byte-array ( n -- byte-array ) 2 >n-byte-array ;
19 : s24>byte-array ( n -- byte-array ) 3 >n-byte-array ;
20 : u24>byte-array ( n -- byte-array ) 3 >n-byte-array ;
21 : s32>byte-array ( n -- byte-array ) 4 >n-byte-array ;
22 : u32>byte-array ( n -- byte-array ) 4 >n-byte-array ;
23 : s64>byte-array ( n -- byte-array ) 8 >n-byte-array ;
24 : u64>byte-array ( n -- byte-array ) 8 >n-byte-array ;
25 : s128>byte-array ( n -- byte-array ) 16 >n-byte-array ;
26 : u128>byte-array ( n -- byte-array ) 16 >n-byte-array ;
27 : write-float ( n -- byte-array ) float>bits 4 >n-byte-array ;
28 : write-double ( n -- byte-array ) double>bits 8 >n-byte-array ;
29 : write-c-string ( byte-array -- byte-array ) { 0 } B{ } append-as ;
30
31 <PRIVATE
32
33 : expand-pack-format ( str -- str' )
34     f swap [
35         dup digit?
36         [ [ 0 or 10 * ] [ CHAR: 0 - ] bi* + f ]
37         [ [ 1 or ] [ <string> ] bi* f swap ] if
38     ] { } map-as "" concat-as nip ; foldable
39
40 CONSTANT: pack-table
41     H{
42         { CHAR: c s8>byte-array }
43         { CHAR: C u8>byte-array }
44         { CHAR: s s16>byte-array }
45         { CHAR: S u16>byte-array }
46         { CHAR: t s24>byte-array }
47         { CHAR: T u24>byte-array }
48         { CHAR: i s32>byte-array }
49         { CHAR: I u32>byte-array }
50         { CHAR: q s64>byte-array }
51         { CHAR: Q u64>byte-array }
52         { CHAR: f write-float }
53         { CHAR: F write-float }
54         { CHAR: d write-double }
55         { CHAR: D write-double }
56         { CHAR: a write-c-string }
57     }
58
59 CONSTANT: unpack-table
60     H{
61         { CHAR: c [ signed-endian> ] }
62         { CHAR: C [ unsigned-endian> ] }
63         { CHAR: s [ signed-endian> ] }
64         { CHAR: S [ unsigned-endian> ] }
65         { CHAR: t [ signed-endian> ] }
66         { CHAR: T [ unsigned-endian> ] }
67         { CHAR: i [ signed-endian> ] }
68         { CHAR: I [ unsigned-endian> ] }
69         { CHAR: q [ signed-endian> ] }
70         { CHAR: Q [ unsigned-endian> ] }
71         { CHAR: f [ unsigned-endian> bits>float ] }
72         { CHAR: F [ unsigned-endian> bits>float ] }
73         { CHAR: d [ unsigned-endian> bits>double ] }
74         { CHAR: D [ unsigned-endian> bits>double ] }
75         ! { CHAR: a read-c-string }
76     }
77
78 CONSTANT: packed-length-table
79     H{
80         { CHAR: c 1 }
81         { CHAR: C 1 }
82         { CHAR: s 2 }
83         { CHAR: S 2 }
84         { CHAR: t 3 }
85         { CHAR: T 3 }
86         { CHAR: i 4 }
87         { CHAR: I 4 }
88         { CHAR: q 8 }
89         { CHAR: Q 8 }
90         { CHAR: f 4 }
91         { CHAR: F 4 }
92         { CHAR: d 8 }
93         { CHAR: D 8 }
94     }
95
96 PRIVATE>
97
98 MACRO: pack ( str -- quot )
99     expand-pack-format
100     [ pack-table at '[ _ execute ] ] { } map-as
101     '[ [ [ _ spread ] input<sequence ] B{ } append-outputs-as ] ;
102
103 : ch>packed-length ( ch -- n )
104     packed-length-table at ; inline
105
106 : packed-length ( str -- n )
107     [ ch>packed-length ] map-sum ;
108
109 : pack-native ( seq str -- seq )
110     '[ _ _ pack ] with-native-endian ; inline
111
112 : pack-be ( seq str -- seq )
113     '[ _ _ pack ] with-big-endian ; inline
114
115 : pack-le ( seq str -- seq )
116     '[ _ _ pack ] with-little-endian ; inline
117
118 <PRIVATE
119
120 : start/end ( seq -- seq1 seq2 )
121     [ cum-sum0 dup ] keep v+ ; inline
122
123 PRIVATE>
124
125 MACRO: unpack ( str -- quot )
126     expand-pack-format
127     [ [ ch>packed-length ] { } map-as start/end ]
128     [ [ unpack-table at ] { } map-as ] bi
129     [ '[ [ _ _ ] dip <slice> @ ] ] 3map
130     '[ _ cleave>array ] ;
131
132 : unpack-native ( seq str -- seq )
133     '[ _ _ unpack ] with-native-endian ; inline
134
135 : unpack-be ( seq str -- seq )
136     '[ _ _ unpack ] with-big-endian ; inline
137
138 : unpack-le ( seq str -- seq )
139     '[ _ _ unpack ] with-little-endian ; inline
140
141 ERROR: packed-read-fail str bytes ;
142
143 <PRIVATE
144
145 : read-packed-bytes ( str -- bytes )
146     dup packed-length [ read dup length ] keep =
147     [ nip ] [ packed-read-fail ] if ; inline
148
149 PRIVATE>
150
151 : read-packed ( str quot -- seq )
152     [ read-packed-bytes ] swap bi ; inline
153
154 : read-packed-le ( str -- seq )
155     [ unpack-le ] read-packed ; inline
156
157 : read-packed-be ( str -- seq )
158     [ unpack-be ] read-packed ; inline
159
160 : read-packed-native ( str -- seq )
161     [ unpack-native ] read-packed ; inline