/*====================================================================*
 -  Copyright (C) 2001 Leptonica.  All rights reserved.
 -  This software is distributed in the hope that it will be
 -  useful, but with NO WARRANTY OF ANY KIND.
 -  No author or distributor accepts responsibility to anyone for the
 -  consequences of using this software, or for whether it serves any
 -  particular purpose or works at all, unless he or she says so in
 -  writing.  Everyone is granted permission to copy, modify and
 -  redistribute this source code, for commercial or non-commercial
 -  purposes, with the following restrictions: (1) the origin of this
 -  source code must not be misrepresented; (2) modified versions must
 -  be plainly marked as such; and (3) this notice may not be removed
 -  or altered from any source or modified source distribution.
 *====================================================================*/

#ifndef ARRAY_ACCESS_H
#define ARRAY_ACCESS_H

/*
 *  arrayaccess.h.vc
 *
 *  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 *  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 *  This version is for MS VC++, which doesn't support expression
 *  statements.  It can give warnings with gcc-4.1.0, so it is not
 *  installed by default.
 *  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 *  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 *
 *
 *  1, 2, 4, 8 and 16 bit data access within an array of 32-bit words
 *
 *  This is used primarily to access 1, 2, 4, 8 and 16 bit pixels
 *  in a line of image data, represented as an array of 32-bit words.
 *
 *     pdata:  pointer to first 32-bit word in the array
 *     n:      index of the pixel in the array
 *
 *  Function calls for these accessors are defined in arrayaccess.c.
 *
 *  However, for efficiency we use macros for all accesses.
 *  Even though the 2 and 4 bit set* accessors are more complicated,
 *  they are about 10% faster than the function calls.
 *
 *  At the end we give code for using invoking the function calls
 *  with the macros.
 */


#include "environ.h"


    /*--------------------------------------------------*
     *                     1 bit access                 *
     *--------------------------------------------------*/
#define  GET_DATA_BIT(pdata, n) \
    ((*((pdata) + ((n) >> 5)) >> (31 - ((n) & 31))) & 1)

#define  SET_DATA_BIT(pdata, n) \
    (*((pdata) + ((n) >> 5)) |= (0x80000000 >> ((n) & 31)))

#define  CLEAR_DATA_BIT(pdata, n) \
    (*((pdata) + ((n) >> 5)) &= ~(0x80000000 >> ((n) & 31)))


    /*--------------------------------------------------*
     *                     2 bit access                 *
     *--------------------------------------------------*/
#define  GET_DATA_DIBIT(pdata, n) \
    ((*((pdata) + ((n) >> 4)) >> (2 * (15 - ((n) & 15)))) & 3)

    /* ANSI C does not support statement expressions */
static l_uint32 *_TEMP_WORD_PTR_;
#define  SET_DATA_DIBIT(pdata, n, val) \
    ( _TEMP_WORD_PTR_ = (pdata) + ((n) >> 4), \
     *_TEMP_WORD_PTR_ &= ~(0xc0000000 >> (2 * ((n) & 15))), \
     *_TEMP_WORD_PTR_ |= ((val) << (30 - 2 * ((n) & 15))) \
    )

#define  CLEAR_DATA_DIBIT(pdata, n) \
    (*((pdata) + ((n) >> 4)) &= ~(0xc0000000 >> (2 * ((n) & 15))))


    /*--------------------------------------------------*
     *                     4 bit access                 *
     *--------------------------------------------------*/
#define  GET_DATA_QBIT(pdata, n) \
     ((*((pdata) + ((n) >> 3)) >> (4 * (7 - ((n) & 7)))) & 0xf)

#define  SET_DATA_QBIT(pdata, n, val) \
    ( _TEMP_WORD_PTR_ = (pdata) + ((n) >> 3), \
     *_TEMP_WORD_PTR_ &= ~(0xf0000000 >> (4 * ((n) & 7))), \
     *_TEMP_WORD_PTR_ |= ((val) << (28 - 4 * ((n) & 7))) \
    )

#define  CLEAR_DATA_QBIT(pdata, n) \
    (*((pdata) + ((n) >> 3)) &= ~(0xf0000000 >> (4 * ((n) & 7))))


    /*--------------------------------------------------*
     *                     8 bit access                 *
     *--------------------------------------------------*/
#ifdef  L_BIG_ENDIAN
#define  GET_DATA_BYTE(pdata, n) \
             (*((l_uint8 *)(pdata) + (n)))
#else  /* L_LITTLE_ENDIAN */
#define  GET_DATA_BYTE(pdata, n) \
             (*(l_uint8 *)((l_uintptr_t)((l_uint8 *)(pdata) + (n)) ^ 3))
#endif  /* L_BIG_ENDIAN */

#ifdef  L_BIG_ENDIAN
#define  SET_DATA_BYTE(pdata, n, val) \
             (*((l_uint8 *)(pdata) + (n)) = (val))
#else  /* L_LITTLE_ENDIAN */
#define  SET_DATA_BYTE(pdata, n, val) \
             (*(l_uint8 *)((l_uintptr_t)((l_uint8 *)(pdata) + (n)) ^ 3) = (val))
#endif  /* L_BIG_ENDIAN */


    /*--------------------------------------------------*
     *                    16 bit access                 *
     *--------------------------------------------------*/
#ifdef  L_BIG_ENDIAN
#define  GET_DATA_TWO_BYTES(pdata, n) \
             (*((l_uint16 *)(pdata) + (n)))
#else  /* L_LITTLE_ENDIAN */
#define  GET_DATA_TWO_BYTES(pdata, n) \
             (*(l_uint16 *)((l_uintptr_t)((l_uint16 *)(pdata) + (n)) ^ 2))
#endif  /* L_BIG_ENDIAN */

#ifdef  L_BIG_ENDIAN
#define  SET_DATA_TWO_BYTES(pdata, n, val) \
             (*((l_uint16 *)(pdata) + (n)) = (val))
#else  /* L_LITTLE_ENDIAN */
#define  SET_DATA_TWO_BYTES(pdata, n, val) \
             (*(l_uint16 *)((l_uintptr_t)((l_uint16 *)(pdata) + (n)) ^ 2) = (val))
#endif  /* L_BIG_ENDIAN */



    /*--------------------------------------------------*
     *  Slower, using function calls for all accessors  *
     *--------------------------------------------------*/
#if 0
#define  GET_DATA_BIT(pdata, n)               l_getDataBit(pdata, n)
#define  SET_DATA_BIT(pdata, n)               l_setDataBit(pdata, n)
#define  CLEAR_DATA_BIT(pdata, n)             l_clearDataBit(pdata, n)

#define  GET_DATA_DIBIT(pdata, n)             l_getDataDibit(pdata, n)
#define  SET_DATA_DIBIT(pdata, n, val)        l_setDataDibit(pdata, n, val)
#define  CLEAR_DATA_DIBIT(pdata, n)           l_clearDataDibit(pdata, n)

#define  GET_DATA_QBIT(pdata, n)              l_getDataQbit(pdata, n)
#define  SET_DATA_QBIT(pdata, n, val)         l_setDataQbit(pdata, n, val)
#define  CLEAR_DATA_QBIT(pdata, n)            l_clearDataQbit(pdata, n)

#define  GET_DATA_BYTE(pdata, n)              l_getDataByte(pdata, n)
#define  SET_DATA_BYTE(pdata, n, val)         l_setDataByte(pdata, n, val)

#define  GET_DATA_TWO_BYTES(pdata, n)         l_getDataTwoBytes(pdata, n)
#define  SET_DATA_TWO_BYTES(pdata, n, val)    l_setDataTwoBytes(pdata, n, val)
#endif


#endif /* ARRAY_ACCESS_H */

