1 ! Copyright (C) 2011 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien.c-types alien.data byte-arrays combinators
4 combinators.smart endian fry hints kernel locals macros math
5 math.ranges sequences sequences.generalizations ;
6 RENAME: be> io.binary => slow-be>
7 RENAME: le> io.binary => slow-le>
8 RENAME: signed-be> io.binary => slow-signed-be>
9 RENAME: signed-le> io.binary => slow-signed-le>
10 RENAME: >be io.binary => >slow-be
11 RENAME: >le io.binary => >slow-le
14 ERROR: bad-length bytes n ;
16 : check-length ( bytes n -- bytes n )
17 2dup [ length ] dip > [ throw-bad-length ] when ; inline
20 : be-range ( n -- range )
21 1 - 8 * 0 -8 <range> ; inline
23 : le-range ( n -- range )
24 1 - 8 * 0 swap 8 <range> ; inline
26 : reassemble-bytes ( range -- quot )
27 [ [ [ ] ] [ '[ _ shift ] ] if-zero ] map
28 '[ [ _ spread ] [ bitor ] reduce-outputs ] ; inline
30 MACRO: reassemble-be ( n -- quot ) be-range reassemble-bytes ;
32 MACRO: reassemble-le ( n -- quot ) le-range reassemble-bytes ;
35 :: n-be> ( bytes n -- x )
36 bytes n check-length drop n firstn-unsafe n reassemble-be ; inline
38 :: n-le> ( bytes n -- x )
39 bytes n check-length drop n firstn-unsafe n reassemble-le ; inline
41 HINTS: n-be> { byte-array object } ;
42 HINTS: n-le> { byte-array object } ;
45 : if-endian ( endian bytes-quot seq-quot -- )
47 compute-native-endianness =
48 [ dup byte-array? ] [ f ] if
53 big-endian [ uint16_t deref ] [ 2 n-be> ] if-endian ;
56 big-endian [ uint32_t deref ] [ 4 n-be> ] if-endian ;
59 big-endian [ uint64_t deref ] [ 8 n-be> ] if-endian ;
69 : signed-be> ( bytes -- x )
70 compute-native-endianness big-endian = [
73 { 2 [ int16_t deref ] }
74 { 4 [ int32_t deref ] }
75 { 8 [ int64_t deref ] }
76 [ drop slow-signed-be> ]
78 ] [ slow-signed-be> ] if
79 ] [ slow-signed-be> ] if ;
82 little-endian [ uint16_t deref ] [ 2 n-le> ] if-endian ;
85 little-endian [ uint32_t deref ] [ 4 n-le> ] if-endian ;
88 little-endian [ uint64_t deref ] [ 8 n-le> ] if-endian ;
98 : signed-le> ( bytes -- x )
99 compute-native-endianness little-endian = [
102 { 2 [ int16_t deref ] }
103 { 4 [ int32_t deref ] }
104 { 8 [ int64_t deref ] }
105 [ drop slow-signed-le> ]
107 ] [ slow-signed-le> ] if
108 ] [ slow-signed-le> ] if ;
110 : >le ( x n -- bytes )
111 compute-native-endianness little-endian = [
113 { 2 [ int16_t <ref> ] }
114 { 4 [ int32_t <ref> ] }
115 { 8 [ int64_t <ref> ] }
120 : >be ( x n -- bytes )
121 compute-native-endianness big-endian = [
123 { 2 [ int16_t <ref> ] }
124 { 4 [ int32_t <ref> ] }
125 { 8 [ int64_t <ref> ] }