MI_Result mof_setupbuffer()

in LCM/codec/mof/parser/utility.c [569:690]


MI_Result mof_setupbuffer(void * data, size_t nBytes, Batch *batch, MOF_Buffer * b)
{
    MOF_ENCODING_TYPE e = ANSI;
    unsigned char *p = (unsigned char *)data;
    memset(b, 0, sizeof(MOF_Buffer));

    _Analysis_assume_(nBytes >= 4);
    {        
        unsigned char c1 = p[0];
        unsigned char c2 = p[1];
        unsigned char c3 = p[2];
        unsigned char c4 = p[3];
        if (c1 == 0xFE && c2 == 0xFF)
        {
            e = UTF16BE;
        }
        else if (c1 == 0xFF && c2 == 0xFE)
        {
            if (c3 == 0 && c4 == 0) // UTF-32 LE
            {
                return MI_RESULT_NOT_SUPPORTED;
            }
            // UTF-16 LE
            e = UTF16LE;
        }
        else if (c1 == 0xEF && c2 == 0xBB && c3 == 0xBF) // UTF-8
        {
            e = UTF8;
        }
        else if (c1 == 0 && c2 == 0 && c3 == 0xFE && c4 == 0xFF) // UTF-32 BE
        {
            return MI_RESULT_NOT_SUPPORTED;
        }
        else if (c1 > 0 && c2 == 0)
        {
            e = UNI;
        }
        else if (c1 == 0 && c2 > 0)
        {
            e = UNIBE;
        }
        else if (c1 ==0 && c2 == 0)
        {
            return MI_RESULT_NOT_SUPPORTED;
        }

        b->e.t = e;
        b->e.o = 0;
        switch(e)
        {
        case UTF8:
            b->e.o = 3;
        case ANSI:
            b->e.u = MI_FALSE;
            break;
        case UTF16LE:
        case UTF16BE:
            b->e.o = 2;
        case UNI:
        case UNIBE:
            b->e.u = MI_TRUE;
            break;
        }
    }
#if !defined(_MSC_VER) 
    /* wchar_t in unix is 4 bytes. Buffer may be coming from windows with proper encoding of UTF-16 ( 2 bytes).
            Once we determine the encoding we appropriately convert it to ASCII on linux. We can't handle 
            characters in unix that doesn't fall under 0<=x<=255. We reject the requests in those cases.*/
    if( b->e.u )
    {
        size_t xCount = 0;
        unsigned short *tempBuf = (unsigned short *) ((unsigned char*)data + b->e.o);
        unsigned char *nullPointer = ((unsigned char*)data + b->e.o + 1);
        // convert UTF to ASCII
        if(( nBytes%2) || !batch)
        {
            return MI_RESULT_NOT_SUPPORTED;
        }
        if( b->e.t == UTF16BE || b->e.t == UNIBE )
        {
            tempBuf = (unsigned short *) ((unsigned char*)data + b->e.o + 1);
            nullPointer = ((unsigned char*)data + b->e.o);
        }
        nBytes = (nBytes-2)/2;
        // allocate memory to hold ascii
        p = (unsigned char*) Batch_Get(batch, nBytes);
        if (p == NULL) return MI_RESULT_SERVER_LIMITS_EXCEEDED;        
        for(; xCount < nBytes; xCount++ )
        {
            if( *nullPointer != '\0' )
                return MI_RESULT_NOT_SUPPORTED;
            
            p[xCount] = (unsigned char) tempBuf[xCount];
            nullPointer +=2;
        }
        b->e.u = MI_FALSE;
        b->e.o = 0;
        b->e.t = ANSI;
    }
#endif
    if(b->e.u && (ptrdiff_t)(p) % (sizeof(wchar_t)) != 0)
    {
        /* Buffer is not alighed with sizeof(wchar_t) */
        /* Need to copy input buffer to alighed memory */   
        if (batch)
        {
            p = (unsigned char*)Batch_Get(batch, nBytes);
            if (p == NULL) return MI_RESULT_SERVER_LIMITS_EXCEEDED;
            memcpy(p, data, nBytes);
        }
        else
        {
            return MI_RESULT_NOT_SUPPORTED;
        }
    }
    b->buf = p;
    b->len = (MI_Uint32)nBytes;
    b->end = p + b->len;
    b->cur = ((char *)b->buf) + b->e.o;
    b->lineNo = 1; /* lineno start from 1 */
    return MI_RESULT_OK;
}