⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 datatype.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*
 * @(#)DataType.cpp 1.0 6/11/98
 * 
 */
 
#include <windows.h>
#include <ctype.h>

#include "assert.h"
#include "datatype.hxx"

#define TRY
#define CATCH   if(0)
#define ENDTRY
#define ERESULT_NOINFO E_FAIL

// SkipWhiteSpace
const WCHAR *
SkipWhiteSpace(const WCHAR * pS, int cch)
{
    while (cch-- && iswspace(*pS))
        pS++;

    return pS;
}


// ParseDecimal
static 
const WCHAR *
ParseDecimal(const WCHAR * pS, int cch, DWORD * pdw)
{
    WCHAR c;
    DWORD dw = 0;

    while (cch-- && iswdigit(c = *pS))
    {       
        dw = dw * 10 + (c - _T('0'));
        pS++;
        if (dw >= ((0xffffffff) / 10 - 9))    // Check for overflow
            break;
    }

    *pdw = dw;
    return pS;
}


// ParseBinHex
HRESULT
ParseBinHex( const WCHAR * pS, long lLen, 
            BYTE * abData, int * pcbSize, 
            const WCHAR ** ppwcNext)
{
    WCHAR wc;
    bool fLow = false;
    const WCHAR * pwc = pS;
    BYTE bByte;
    byte result;

    // fake a leading zero
    if ( lLen % 2 != 0)
    {
        bByte = 0;
        fLow = true;
    }

    *pcbSize = (lLen + 1) >> 1; // divide in 1/2 with round up

    // walk hex digits pairing them up and shoving the value of each pair into a byte
    while ( lLen-- > 0)
    {
        wc = *pwc++;
        if (wc >= L'a' && wc <= L'f')
        {
            result = 10 + (wc - L'a');
        }
        else if (wc >= L'A' && wc <= L'F')
        {
            result = 10 + (wc - L'A');
        }
        else if (wc >= L'0' && wc <= L'9')
        {
            result = wc - L'0';
        }
        else if (iswspace(wc))
        {
            continue; // skip whitespace
        }
        else
        {
            goto Error;
        }

        assert((0 <= result) && (result < 16));
        if ( fLow)
        {
            bByte += (BYTE)result;
            *abData++ = bByte;
            fLow = false;
        }
        else
        {
            // shift nibble into top half of byte
            bByte = (BYTE)(result << 4);
            fLow = true;
        }   
    }

//Cleanup:
    if (ppwcNext)
        *ppwcNext = pwc;
    return S_OK;

Error:
    return E_FAIL;
}



// ParseISO8601
HRESULT
ParseISO8601(const WCHAR * pS, int cch, 
             DataType dt, DATE * pdate, 
             const WCHAR ** ppwcNext)
{
    HRESULT hr = S_OK;
    UDATE udate;
    const WCHAR * pN;
    union { // enforce 64-bit alignment of ftTime
        FILETIME ftTime;
        __int64  __unused000;
    };
    __int64 i64Offset;
    int iSign = 0;
    DWORD dw;
    const WCHAR * pSStart = pS;

    // make sure the enums are ordered according to logic below
    assert(DT_DATE_ISO8601 < DT_DATETIME_ISO8601 &&
        DT_DATETIME_ISO8601 < DT_DATETIME_ISO8601TZ &&
        DT_DATETIME_ISO8601TZ < DT_TIME_ISO8601 &&
        DT_TIME_ISO8601 < DT_TIME_ISO8601TZ);

    memset(&udate, 0, sizeof(udate));
    udate.st.wMonth = 1;
    udate.st.wDay = 1;
    pS = SkipWhiteSpace(pS, cch);
    cch -= (int)(pS - pSStart);
    // parse date if allowed
    if (dt < DT_TIME_ISO8601)
    {
        pN = ParseDecimal(pS, cch, &dw);
        if (pN - pS != 4) // 4 digits
            goto Error;
        // HACK: VarDateFromUdate treats 2digit years specially, for y2k compliance
        if (dw < 100)
            goto Error;
        udate.st.wYear = (WORD) dw;
        cch -= 4;
        pS = pN;
        if (*pS == _T('-'))
        {
            pN = ParseDecimal(pS + 1, --cch, &dw);
            if (pN - pS != 3 || 0 == dw || dw > 12) // 2 digits + '-'
                goto Error;
            udate.st.wMonth = (WORD) dw;
            cch -= 2;
            pS = pN;
            if (*pS == _T('-'))
            {
                pN = ParseDecimal(pS + 1, --cch, &dw);
                if (pN - pS != 3 || 0 == dw || dw > 31) // 2 digits + '-'
                    goto Error;
                udate.st.wDay = (WORD) dw;
                cch -= 2;
                pS = pN;
            }
        }
        if (cch && dt >= DT_DATETIME_ISO8601)
        {
            // swallow T
            // Assume starts with T ?
            if (*pS != _T('T'))
                goto Error;
            pS++;
            cch--;
        }
    }
    else
    {
        udate.st.wYear = 1899;
        udate.st.wMonth = 12;
        udate.st.wDay = 30;
    }

    // parse time if allowed
    if (cch && dt >= DT_DATETIME_ISO8601)
    {
        pN = ParseDecimal(pS, cch, &dw);
        if (pN - pS != 2 || dw > 24) // 2 digits + 'T'
            goto Error;
        udate.st.wHour = (WORD) dw;
        cch -= 2;
        pS = pN;
        if (*pS == _T(':'))
        {
            pN = ParseDecimal(pS + 1, --cch, &dw);
            if (pN - pS != 3 || dw > 59) // 2 digits + ':'
                goto Error;
            udate.st.wMinute = (WORD) dw;
            cch -= 2;
            pS = pN;
            if (*pS == _T(':'))
            {
                pN = ParseDecimal(pS + 1, --cch, &dw);
                if (pN - pS != 3 || dw > 59) // 2 digits + ':'
                    goto Error;
                udate.st.wSecond = (WORD) dw;
                cch -= 2;
                pS = pN;
                if (*pS == _T('.'))
                {
                    pN = ParseDecimal(pS + 1, --cch, &dw);
                    int d = (int)(3 - (pN - (pS + 1)));
                    if (d > 2 || dw > 999999999) // at least 1 digit, not more than 9 digits
                        goto Error;
                    cch -= (int)(pN - pS - 1);
                    pS = pN;
                    while (d > 0)
                    {
                        dw *= 10;
                        d--;
                    }
                    while (d < 0)
                    {
                        dw /= 10;
                        d++;
                    }
                    udate.st.wMilliseconds = (WORD) dw;
                }
            }
        }

        // watch for 24:01... etc
        if (udate.st.wHour == 24 && (udate.st.wMinute > 0 || udate.st.wSecond > 0 || udate.st.wMilliseconds > 0))
            goto Error;

        // parse timezone if allowed
        if (cch && (dt == DT_DATETIME_ISO8601TZ || dt == DT_TIME_ISO8601TZ))
        {
            if (*pS == _T('+'))
                iSign = 1;
            else if (*pS == _T('-'))
                iSign = -1;
            else if (*pS == _T('Z'))
            {
                pS++;
                cch--;
            }
            if (iSign)
            {
                if (!SystemTimeToFileTime(&udate.st, &ftTime))
                    goto Error;
                pN = ParseDecimal(pS + 1, --cch, &dw);
                if (pN - pS != 3) // 2 digits + '+' or '-'
                    goto Error;
                i64Offset = (__int64)dw;
                cch -= 2;
                pS = pN;
                if (*pS != ':')
                    goto Error;
                pN = ParseDecimal(pS + 1, --cch, &dw);
                if (pN - pS != 3) // 2 digits + ':'
                    goto Error;
                cch -= 2;
                pS = pN;
                // convert to 100 nanoseconds
                i64Offset = 10000000 * 60 * ((__int64)dw + 60 * i64Offset);
                *(__int64 *)&ftTime = *(__int64 *)&ftTime + iSign * i64Offset;
                if (!FileTimeToSystemTime(&ftTime, &udate.st))
                    goto Error;
            }
        }
    }

    hr = VarDateFromUdate(&udate, 0, pdate);
    if (FAILED(hr))
        goto Cleanup;

Cleanup:
    if (ppwcNext)
        *ppwcNext = pS;

    return hr;

Error:
    hr = E_FAIL;
    goto Cleanup;
}


HRESULT
UnparseDecimal( ce::wstring * pSBuffer, WORD num, long digits)
{
    HRESULT hr = S_OK;
    unsigned short digit;
    unsigned short place = 1;
    // since num is WORD == 16bits, we are better off useing ushort-s above...
    if ( digits > 5)
    {
        hr = E_INVALIDARG;
        goto Cleanup;
    }
    // start with the most significant digit
    while( --digits) place *= 10;

    // for each digit, pull the digit out of num and store it in the string buffer
    while ( place > 0)
    {
        digit = num/place;
        if (digit > 9)
        {
            hr = E_INVALIDARG;
            goto Cleanup;
        }
        pSBuffer->append(_T('0') + digit);
        num -= digit*place;
        place /= 10;
    }
Cleanup:
    return hr;
}


HRESULT
UnparseISO8601( ce::wstring * pReturn, DataType dt, const DATE * pdate)
{
    HRESULT         hr = S_OK;
    UDATE           udate;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -