PORT_Assert((inBufLen % 2) == 0); if ((inBufLen % 2) != 0) { *outBufLen = 0; return PR_FALSE; }
PR_IMPLEMENT(PRBool)sec_port_ucs2_utf8_conversion_function(  PRBool toUnicode,  unsigned char *inBuf,  unsigned int inBufLen,  unsigned char *outBuf,  unsigned int maxOutBufLen,  unsigned int *outBufLen){#ifndef TEST_UTF8  PORT_Assert((unsigned int *)NULL != outBufLen);#endif /* TEST_UTF8 */  if( toUnicode ) {    unsigned int i, len = 0;    for( i = 0; i < inBufLen; ) {      if( (inBuf[i] & 0x80) == 0x00 ) {        i += 1;        len += 2;      } else if( (inBuf[i] & 0xE0) == 0xC0 ) {        i += 2;        len += 2;      } else if( (inBuf[i] & 0xF0) == 0xE0 ) {        i += 3;        len += 2;#ifdef UTF16      } else if( (inBuf[i] & 0xF8) == 0xF0 ) {         i += 4;        len += 4;        if( (inBuf[i] & 0x04) &&             ((inBuf[i] & 0x03) || (inBuf[i+1] & 0x30)) ) {          /* Not representable as UTF16 */          return PR_FALSE;        }#endif /* UTF16 */      } else return PR_FALSE;    }    if( len > maxOutBufLen ) {      *outBufLen = len;      return PR_FALSE;    }    len = 0;    for( i = 0; i < inBufLen; ) {      if( (inBuf[i] & 0x80) == 0x00 ) {        /* 0000-007F <- 0xxxxxx */        /* 0abcdefg -> 00000000 0abcdefg */        outBuf[len+H_0] = 0x00;        outBuf[len+H_1] = inBuf[i+0] & 0x7F;        i += 1;        len += 2;      } else if( (inBuf[i] & 0xE0) == 0xC0 ) {        if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;        /* 0080-07FF <- 110xxxxx 10xxxxxx */        /* 110abcde 10fghijk -> 00000abc defghijk */        outBuf[len+H_0] = ((inBuf[i+0] & 0x1C) >> 2);        outBuf[len+H_1] = ((inBuf[i+0] & 0x03) << 6) | ((inBuf[i+1] & 0x3F) >> 0);        i += 2;        len += 2;      } else if( (inBuf[i] & 0xF0) == 0xE0 ) {        if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;        if( (inBuf[i+2] & 0xC0) != 0x80 ) return PR_FALSE;        /* 0800-FFFF <- 1110xxxx 10xxxxxx 10xxxxxx */        /* 1110abcd 10efghij 10klmnop -> abcdefgh ijklmnop */        outBuf[len+H_0] = ((inBuf[i+0] & 0x0F) << 4) | ((inBuf[i+1] & 0x3C) >> 2);        outBuf[len+H_1] = ((inBuf[i+1] & 0x03) << 6) | ((inBuf[i+2] & 0x3F) >> 0);        i += 3;        len += 2;#ifdef UTF16      } else if( (inBuf[i] & 0xF8) == 0xF0 ) {         int abcde, BCDE;        if( (inBuf[i+1] & 0xC0) != 0x80 ) return PR_FALSE;        if( (inBuf[i+2] & 0xC0) != 0x80 ) return PR_FALSE;        if( (inBuf[i+3] & 0xC0) != 0x80 ) return PR_FALSE;        /* 0001 0000-001F FFFF <- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */        /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx -> [D800-DBFF] [DC00-DFFF] */                   /* 11110abc 10defghi 10jklmno 10pqrstu ->            { Let 0BCDE = abcde - 1 }           110110BC DEfghijk 110111lm nopqrstu */        abcde = ((inBuf[i+0] & 0x07) << 2) | ((inBuf[i+1] & 0x30) >> 4);        BCDE = abcde - 1;#ifndef TEST_UTF8        PORT_Assert(BCDE < 0x10); /* should have been caught above */#endif /* TEST_UTF8 */        outBuf[len+0+H_0] = 0xD8 | ((BCDE & 0x0C) >> 2);        outBuf[len+0+H_1] = ((BCDE & 0x03) << 6)                       | ((inBuf[i+1] & 0x0F) << 2)                      | ((inBuf[i+2] & 0x30) >> 4);        outBuf[len+2+H_0] = 0xDC | ((inBuf[i+2] & 0x0C) >> 2);        outBuf[len+2+H_1] = ((inBuf[i+2] & 0x03) << 6) | ((inBuf[i+3] & 0x3F) >> 0);        i += 4;        len += 4;#endif /* UTF16 */      } else return PR_FALSE;    }    *outBufLen = len;    return PR_TRUE;  } else {    unsigned int i, len = 0;    for( i = 0; i < inBufLen; i += 2 ) {      if( (inBuf[i+H_0] == 0x00) && ((inBuf[i+H_0] & 0x80) == 0x00) ) len += 1;      else if( inBuf[i+H_0] < 0x08 ) len += 2;#ifdef UTF16      else if( ((inBuf[i+0+H_0] & 0xDC) == 0xD8) ) {        if( ((inBuf[i+2+H_0] & 0xDC) == 0xDC) && ((inBufLen - i) > 2) ) {          i += 2;          len += 4;        } else {          return PR_FALSE;        }      }#endif /* UTF16 */      else len += 3;    }    if( len > maxOutBufLen ) {      *outBufLen = len;      return PR_FALSE;    }    len = 0;    for( i = 0; i < inBufLen; i += 2 ) {      if( (inBuf[i+H_0] == 0x00) && ((inBuf[i+H_1] & 0x80) == 0x00) ) {        /* 0000-007F -> 0xxxxxx */        /* 00000000 0abcdefg -> 0abcdefg */        outBuf[len] = inBuf[i+H_1] & 0x7F;        len += 1;      } else if( inBuf[i+H_0] < 0x08 ) {        /* 0080-07FF -> 110xxxxx 10xxxxxx */        /* 00000abc defghijk -> 110abcde 10fghijk */        outBuf[len+0] = 0xC0 | ((inBuf[i+H_0] & 0x07) << 2)                              | ((inBuf[i+H_1] & 0xC0) >> 6);        outBuf[len+1] = 0x80 | ((inBuf[i+H_1] & 0x3F) >> 0);        len += 2;#ifdef UTF16      } else if( (inBuf[i+H_0] & 0xDC) == 0xD8 ) {        int abcde, BCDE;#ifndef TEST_UTF8        PORT_Assert(((inBuf[i+2+H_0] & 0xDC) == 0xDC) && ((inBufLen - i) > 2));#endif /* TEST_UTF8 */        /* D800-DBFF DC00-DFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */        /* 110110BC DEfghijk 110111lm nopqrstu ->           { Let abcde = BCDE + 1 }           11110abc 10defghi 10jklmno 10pqrstu */        BCDE = ((inBuf[i+H_0] & 0x03) << 2) | ((inBuf[i+H_1] & 0xC0) >> 6);        abcde = BCDE + 1;        outBuf[len+0] = 0xF0 | ((abcde & 0x1C) >> 2);        outBuf[len+1] = 0x80 | ((abcde & 0x03) << 4)                              | ((inBuf[i+0+H_1] & 0x3C) >> 2);        outBuf[len+2] = 0x80 | ((inBuf[i+0+H_1] & 0x03) << 4)                             | ((inBuf[i+2+H_0] & 0x03) << 2)                             | ((inBuf[i+2+H_1] & 0xC0) >> 6);        outBuf[len+3] = 0x80 | ((inBuf[i+2+H_1] & 0x3F) >> 0);        i += 2;        len += 4;#endif /* UTF16 */      } else {        /* 0800-FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */        /* abcdefgh ijklmnop -> 1110abcd 10efghij 10klmnop */        outBuf[len+0] = 0xE0 | ((inBuf[i+H_0] & 0xF0) >> 4);        outBuf[len+1] = 0x80 | ((inBuf[i+H_0] & 0x0F) << 2)                              | ((inBuf[i+H_1] & 0xC0) >> 6);        outBuf[len+2] = 0x80 | ((inBuf[i+H_1] & 0x3F) >> 0);        len += 3;      }    }    *outBufLen = len;    return PR_TRUE;  }}