Do everything if needed

Only to note everything I meet.

选择合适的数据类型

WINCE6中SDBus驱动中有如下代码,用来从一段给定的内存中的指定位置取出指定的几位数据。

就这样一个功能,使用了如此多的代码,我个人认为是由于使用了错误的数据类型从而使其变得很复杂

 

// Shifts pbInput down by dwBitOffset.

static

VOID

ShiftBytes(PBYTE pbInput, ULONG cbInput, DWORD dwBitOffset, PBYTE pbOutput)

{

    PREFAST_DEBUGCHK(pbInput);

    PREFAST_DEBUGCHK(pbOutput);

 

    DWORD dwByteIndex = dwBitOffset / 8;

    dwBitOffset %= 8;

 

    DWORD dwRemainderShift = 8 - dwBitOffset;

 

    // Only copy 4 bytes max.

    DWORD dwEndIndex = min(dwByteIndex + sizeof(DWORD), cbInput);

    DWORD dwCurrOutputIndex = 0;

    while (dwByteIndex < dwEndIndex) {

        DEBUGCHK(dwCurrOutputIndex < sizeof(DWORD));

        DEBUGCHK(dwByteIndex < cbInput);

 

        pbOutput[dwCurrOutputIndex] = pbInput[dwByteIndex] >> dwBitOffset;

         ++dwByteIndex;

         if (dwByteIndex != cbInput) {

            BYTE bTemp = pbInput[dwByteIndex];

            bTemp <<= dwRemainderShift;

            pbOutput[dwCurrOutputIndex] |= bTemp;

        }

         ++dwCurrOutputIndex;

    }

}

 

 

///////////////////////////////////////////////////////////////////////////////

//  GetBitSlice - Get a bit slice from a stream of bytes

//  Input:  pBuffer - buffer containing data stream

//          cbBuffer - size of buffer in bytes

//          dwBitOffset - bit offset from start of buffer

//          ucBitCount - number of bits (less than or equal to 32)

//  Output:

//

//  Return: returns a DWORD contain the bit slice shifted to fill the least significant bits

//  Notes:  will raise an SEH exception if integer overflow occurs

///////////////////////////////////////////////////////////////////////////////

DWORD CSDDevice::GetBitSlice(PUCHAR pBuffer, ULONG cbBuffer, DWORD dwBitOffset, UCHAR ucBitCount)

{

    UCHAR rgbShifted[4] = { 0 };

 

    if (ucBitCount > 32) {

        DEBUG_CHECK(FALSE, (TEXT("GetBitSlice: invalid number of bits \n")));

        return 0;

    }

     typedef SafeInt<DWORD> SafeDW;

    // Exception will be raised on the next line if there is an overflow.

    if ( (SafeDW(dwBitOffset) + SafeDW(ucBitCount)) > (SafeDW(cbBuffer) * 8) ) {

        DEBUG_CHECK(FALSE, (TEXT("GetBitSlice: invalid bit offset given the number of bits \n")));

        return 0;

    }

 

    // Shift the pBuffer down by dwBitOffset bits.

    ShiftBytes(pBuffer, cbBuffer, dwBitOffset, rgbShifted);

 

    DWORD dwUsedBytes; // How many bytes have valid data.

 

    if (ucBitCount % 8 == 0) {

        // Return a byte multiple.

        dwUsedBytes = ucBitCount / 8;

    }

    else {

        // Clear the last used byte of upper bits.

        DWORD dwLastByteIndex = (ucBitCount - 1) / 8;

        DWORD dwRemainderShift = 8 - (ucBitCount % 8);

        rgbShifted[dwLastByteIndex] <<= dwRemainderShift;

        rgbShifted[dwLastByteIndex] >>= dwRemainderShift;

        dwUsedBytes = dwLastByteIndex + 1;

    }

 

    // Clear the unused bytes.

    if (dwUsedBytes != sizeof(rgbShifted)) {

        memset(rgbShifted + dwUsedBytes, 0, sizeof(rgbShifted) - dwUsedBytes);

    }

     DWORD dwRet;

    memcpy(&dwRet, rgbShifted, sizeof(dwRet));

 

    return dwRet;

}

 

以下是我自己为了实现相同功能而写的代码

  • WORD GetBitValue( PBYTE pBuf, DWORD dwBit, DWORD dwNum )
  • {
  •     DWORD dwByte=dwBit/8;
  •     DWORD dwBitinByte=dwBit & 0x7;

 

  •     if(dwBitinByte + dwNum >24 )
  •         return 0; //Not supported.
  •     else if(dwBitinByte + dwNum >16 )
  •         return (pBuf[dwByte]>>(dwBitinByte) ) |
  •                    (pBuf[dwByte+1]<<( 8- dwBitinByte) ) |
  •                   ( pBuf[dwByte+2] << (16-dwBitinByte) );

 

  •     else if(dwBitinByte + dwNum >8 )
  •         return (pBuf[dwByte]>>(dwBitinByte) ) |  (pBuf[dwByte+1]<<( 8- dwBitinByte) ) ;
  •     else
  •         return pBuf[dwByte]>>(dwBitinByte);
  • }

 

当然我的代码有点缺陷:取出的数据高位没有清零,要做到这点是很容易的。

posted on 2010-07-19 06:58  microsun  阅读(492)  评论(0编辑  收藏  举报

导航