Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

292 lines (243 sloc) 6.56 kB
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "config.h"
#include "sm.h"
static int
enc_char(uint8 *utf8Buffer, uint32 ucs4Char)
{
int utf8Length = 1;
if (ucs4Char < 0x80)
{
*utf8Buffer = (uint8)ucs4Char;
}
else
{
int i;
uint32 a = ucs4Char >> 11;
utf8Length = 2;
while(a)
{
a >>= 5;
utf8Length++;
}
i = utf8Length;
while(--i)
{
utf8Buffer[i] = (uint8)((ucs4Char & 0x3F) | 0x80);
ucs4Char >>= 6;
}
*utf8Buffer = (uint8)(0x100 - (1 << (8-utf8Length)) + ucs4Char);
}
return utf8Length;
}
static JSBool
enc_charbuf(const jschar* src, size_t srclen, char* dst, size_t* dstlenp)
{
size_t i;
size_t utf8Len;
size_t dstlen = *dstlenp;
size_t origDstlen = dstlen;
jschar c;
jschar c2;
uint32 v;
uint8 utf8buf[6];
if(!dst)
{
dstlen = origDstlen = (size_t) -1;
}
while(srclen)
{
c = *src++;
srclen--;
if((c >= 0xDC00) && (c <= 0xDFFF)) goto bad_surrogate;
if(c < 0xD800 || c > 0xDBFF)
{
v = c;
}
else
{
if(srclen < 1) goto buffer_too_small;
c2 = *src++;
srclen--;
if ((c2 < 0xDC00) || (c2 > 0xDFFF))
{
c = c2;
goto bad_surrogate;
}
v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
}
if(v < 0x0080)
{
/* no encoding necessary - performance hack */
if(!dstlen) goto buffer_too_small;
if(dst) *dst++ = (char) v;
utf8Len = 1;
}
else
{
utf8Len = enc_char(utf8buf, v);
if(utf8Len > dstlen) goto buffer_too_small;
if(dst)
{
for (i = 0; i < utf8Len; i++)
{
*dst++ = (char) utf8buf[i];
}
}
}
dstlen -= utf8Len;
}
*dstlenp = (origDstlen - dstlen);
return JS_TRUE;
bad_surrogate:
*dstlenp = (origDstlen - dstlen);
return JS_FALSE;
buffer_too_small:
*dstlenp = (origDstlen - dstlen);
return JS_FALSE;
}
char*
enc_string(JSContext* cx, jsval arg, size_t* buflen)
{
JSString* str = NULL;
const jschar* src = NULL;
char* bytes = NULL;
size_t srclen = 0;
size_t byteslen = 0;
str = JS_ValueToString(cx, arg);
if(!str) goto error;
#ifdef SM185
src = JS_GetStringCharsAndLength(cx, str, &srclen);
#else
src = JS_GetStringChars(str);
srclen = JS_GetStringLength(str);
#endif
if(!enc_charbuf(src, srclen, NULL, &byteslen)) goto error;
bytes = (char*) JS_malloc(cx, (byteslen) + 1);
bytes[byteslen] = 0;
if(!enc_charbuf(src, srclen, bytes, &byteslen)) goto error;
if(buflen) *buflen = byteslen;
goto success;
error:
if(bytes != NULL) JS_free(cx, bytes);
bytes = NULL;
success:
return bytes;
}
static uint32
dec_char(const uint8 *utf8Buffer, int utf8Length)
{
uint32 ucs4Char;
uint32 minucs4Char;
/* from Unicode 3.1, non-shortest form is illegal */
static const uint32 minucs4Table[] = {
0x00000080, 0x00000800, 0x0001000, 0x0020000, 0x0400000
};
if (utf8Length == 1)
{
ucs4Char = *utf8Buffer;
}
else
{
ucs4Char = *utf8Buffer++ & ((1<<(7-utf8Length))-1);
minucs4Char = minucs4Table[utf8Length-2];
while(--utf8Length)
{
ucs4Char = ucs4Char<<6 | (*utf8Buffer++ & 0x3F);
}
if(ucs4Char < minucs4Char || ucs4Char == 0xFFFE || ucs4Char == 0xFFFF)
{
ucs4Char = 0xFFFD;
}
}
return ucs4Char;
}
static JSBool
dec_charbuf(const char *src, size_t srclen, jschar *dst, size_t *dstlenp)
{
uint32 v;
size_t offset = 0;
size_t j;
size_t n;
size_t dstlen = *dstlenp;
size_t origDstlen = dstlen;
if(!dst) dstlen = origDstlen = (size_t) -1;
while(srclen)
{
v = (uint8) *src;
n = 1;
if(v & 0x80)
{
while(v & (0x80 >> n))
{
n++;
}
if(n > srclen) goto buffer_too_small;
if(n == 1 || n > 6) goto bad_character;
for(j = 1; j < n; j++)
{
if((src[j] & 0xC0) != 0x80) goto bad_character;
}
v = dec_char((const uint8 *) src, n);
if(v >= 0x10000)
{
v -= 0x10000;
if(v > 0xFFFFF || dstlen < 2)
{
*dstlenp = (origDstlen - dstlen);
return JS_FALSE;
}
if(dstlen < 2) goto buffer_too_small;
if(dst)
{
*dst++ = (jschar)((v >> 10) + 0xD800);
v = (jschar)((v & 0x3FF) + 0xDC00);
}
dstlen--;
}
}
if(!dstlen) goto buffer_too_small;
if(dst) *dst++ = (jschar) v;
dstlen--;
offset += n;
src += n;
srclen -= n;
}
*dstlenp = (origDstlen - dstlen);
return JS_TRUE;
bad_character:
*dstlenp = (origDstlen - dstlen);
return JS_FALSE;
buffer_too_small:
*dstlenp = (origDstlen - dstlen);
return JS_FALSE;
}
JSString*
dec_string(JSContext* cx, const char* bytes, size_t byteslen)
{
JSString* str = NULL;
jschar* chars = NULL;
size_t charslen;
if(!dec_charbuf(bytes, byteslen, NULL, &charslen)) goto error;
chars = (jschar*) JS_malloc(cx, (charslen + 1) * sizeof(jschar));
if(!chars) return NULL;
chars[charslen] = 0;
if(!dec_charbuf(bytes, byteslen, chars, &charslen)) goto error;
str = JS_NewUCString(cx, chars, charslen - 1);
if(!str) goto error;
goto success;
error:
if(chars != NULL) JS_free(cx, chars);
str = NULL;
success:
return str;
}
Jump to Line
Something went wrong with that request. Please try again.