! Copyright (C) 2011 Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. USING: alien.c-types alien.data byte-arrays combinators combinators.smart endian fry hints kernel locals macros math math.ranges sequences sequences.generalizations ; RENAME: be> io.binary => slow-be> RENAME: le> io.binary => slow-le> RENAME: signed-be> io.binary => slow-signed-be> RENAME: signed-le> io.binary => slow-signed-le> RENAME: >be io.binary => >slow-be RENAME: >le io.binary => >slow-le IN: io.binary.fast ERROR: bad-length bytes n ; : check-length ( bytes n -- bytes n ) 2dup [ length ] dip > [ bad-length ] when ; inline << : be-range ( n -- range ) 1 - 8 * 0 -8 ; inline : le-range ( n -- range ) 1 - 8 * 0 swap 8 ; inline : reassemble-bytes ( range -- quot ) [ [ [ ] ] [ '[ _ shift ] ] if-zero ] map '[ [ _ spread ] [ bitor ] reduce-outputs ] ; inline MACRO: reassemble-be ( n -- quot ) be-range reassemble-bytes ; MACRO: reassemble-le ( n -- quot ) le-range reassemble-bytes ; >> :: n-be> ( bytes n -- x ) bytes n check-length drop n firstn-unsafe n reassemble-be ; inline :: n-le> ( bytes n -- x ) bytes n check-length drop n firstn-unsafe n reassemble-le ; inline HINTS: n-be> { byte-array object } ; HINTS: n-le> { byte-array object } ; : 2be> ( bytes -- x ) big-endian [ uint16_t deref ] [ 2 n-be> ] if-endian ; : 4be> ( bytes -- x ) big-endian [ uint32_t deref ] [ 4 n-be> ] if-endian ; : 8be> ( bytes -- x ) big-endian [ uint64_t deref ] [ 8 n-be> ] if-endian ; : be> ( bytes -- x ) dup length { { 2 [ 2be> ] } { 4 [ 4be> ] } { 8 [ 8be> ] } [ drop slow-be> ] } case ; : signed-be> ( bytes -- x ) compute-native-endianness big-endian = [ dup byte-array? [ dup length { { 2 [ int16_t deref ] } { 4 [ int32_t deref ] } { 8 [ int64_t deref ] } [ drop slow-signed-be> ] } case ] [ slow-signed-be> ] if ] [ slow-signed-be> ] if ; : 2le> ( bytes -- x ) little-endian [ uint16_t deref ] [ 2 n-le> ] if-endian ; : 4le> ( bytes -- x ) little-endian [ uint32_t deref ] [ 4 n-le> ] if-endian ; : 8le> ( bytes -- x ) little-endian [ uint64_t deref ] [ 8 n-le> ] if-endian ; : le> ( bytes -- x ) dup length { { 2 [ 2le> ] } { 4 [ 4le> ] } { 8 [ 8le> ] } [ drop slow-le> ] } case ; : signed-le> ( bytes -- x ) compute-native-endianness little-endian = [ dup byte-array? [ dup length { { 2 [ int16_t deref ] } { 4 [ int32_t deref ] } { 8 [ int64_t deref ] } [ drop slow-signed-le> ] } case ] [ slow-signed-le> ] if ] [ slow-signed-le> ] if ; : >le ( x n -- bytes ) compute-native-endianness little-endian = [ { { 2 [ int16_t ] } { 4 [ int32_t ] } { 8 [ int64_t ] } [ >slow-le ] } case ] [ >slow-le ] if ; : >be ( x n -- bytes ) compute-native-endianness big-endian = [ { { 2 [ int16_t ] } { 4 [ int32_t ] } { 8 [ int64_t ] } [ >slow-be ] } case ] [ >slow-be ] if ;