diff options
author | hobbs <hobbs> | 2006-10-05 21:24:39 (GMT) |
---|---|---|
committer | hobbs <hobbs> | 2006-10-05 21:24:39 (GMT) |
commit | d78a8ea8c98971dec54e3bf5c738432029bb7e61 (patch) | |
tree | 82fd1cd2dec7ddd5c18e1f14ddf44d3e52aa27c6 /generic/tclEncoding.c | |
parent | 46aff41e83607a2efd59982d1393cff759ba692e (diff) | |
download | tcl-d78a8ea8c98971dec54e3bf5c738432029bb7e61.zip tcl-d78a8ea8c98971dec54e3bf5c738432029bb7e61.tar.gz tcl-d78a8ea8c98971dec54e3bf5c738432029bb7e61.tar.bz2 |
* generic/tcl.h: note limitation on changing Tcl_UniChar size
* generic/tclEncoding.c (UtfToUnicodeProc, UnicodeToUtfProc):
* tests/encoding.test (encoding-16.1): fix alignment issues in
unicode <> utf conversion procs. [Bug 1122671]
Diffstat (limited to 'generic/tclEncoding.c')
-rw-r--r-- | generic/tclEncoding.c | 60 |
1 files changed, 34 insertions, 26 deletions
diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index a766013..65d6f9d 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclEncoding.c,v 1.44 2006/09/26 23:01:11 kennykb Exp $ + * RCS: @(#) $Id: tclEncoding.c,v 1.45 2006/10/05 21:24:40 hobbs Exp $ */ #include "tclInt.h" @@ -2288,9 +2288,10 @@ UnicodeToUtfProc( * correspond to the bytes stored in the * output buffer. */ { - CONST Tcl_UniChar *wSrc, *wSrcStart, *wSrcEnd; + CONST char *srcStart, *srcEnd; char *dstEnd, *dstStart; int result, numChars; + Tcl_UniChar ch; result = TCL_OK; if ((srcLen % sizeof(Tcl_UniChar)) != 0) { @@ -2299,33 +2300,31 @@ UnicodeToUtfProc( srcLen *= sizeof(Tcl_UniChar); } - wSrc = (Tcl_UniChar *) src; - - wSrcStart = (Tcl_UniChar *) src; - wSrcEnd = (Tcl_UniChar *) (src + srcLen); + srcStart = src; + srcEnd = src + srcLen; dstStart = dst; dstEnd = dst + dstLen - TCL_UTF_MAX; - for (numChars = 0; wSrc < wSrcEnd; numChars++) { + for (numChars = 0; src < srcEnd; numChars++) { if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; } - /* - * Special case for 1-byte utf chars for speed. + * Special case for 1-byte utf chars for speed. Make sure we + * work with Tcl_UniChar-size data. */ - - if (*wSrc && *wSrc < 0x80) { - *dst++ = (char) *wSrc; + ch = *(Tcl_UniChar *)src; + if (ch && ch < 0x80) { + *dst++ = *src; } else { - dst += Tcl_UniCharToUtf(*wSrc, dst); + dst += Tcl_UniCharToUtf(ch, dst); } - wSrc++; + src += sizeof(Tcl_UniChar); } - *srcReadPtr = (char *) wSrc - (char *) wSrcStart; + *srcReadPtr = src - srcStart; *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; @@ -2375,9 +2374,9 @@ UtfToUnicodeProc( * correspond to the bytes stored in the * output buffer. */ { - CONST char *srcStart, *srcEnd, *srcClose; - Tcl_UniChar *wDst, *wDstStart, *wDstEnd; + CONST char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd; int result, numChars; + Tcl_UniChar ch; srcStart = src; srcEnd = src + srcLen; @@ -2386,9 +2385,8 @@ UtfToUnicodeProc( srcClose -= TCL_UTF_MAX; } - wDst = (Tcl_UniChar *) dst; - wDstStart = (Tcl_UniChar *) dst; - wDstEnd = (Tcl_UniChar *) (dst + dstLen - sizeof(Tcl_UniChar)); + dstStart = dst; + dstEnd = dst + dstLen - sizeof(Tcl_UniChar); result = TCL_OK; for (numChars = 0; src < srcEnd; numChars++) { @@ -2401,16 +2399,26 @@ UtfToUnicodeProc( result = TCL_CONVERT_MULTIBYTE; break; } - if (wDst > wDstEnd) { + if (dst > dstEnd) { result = TCL_CONVERT_NOSPACE; break; - } - src += TclUtfToUniChar(src, wDst); - wDst++; + } + src += TclUtfToUniChar(src, &ch); + /* + * Need to handle this in a way that won't cause misalignment + * by casting dst to a Tcl_UniChar. [Bug 1122671] + * XXX: This hard-codes the assumed size of Tcl_UniChar as 2. + */ +#ifdef WORDS_BIGENDIAN + *dst++ = (ch >> 8); + *dst++ = (ch & 0xFF); +#else + *dst++ = (ch & 0xFF); + *dst++ = (ch >> 8); +#endif } - *srcReadPtr = src - srcStart; - *dstWrotePtr = (char *) wDst - (char *) wDstStart; + *dstWrotePtr = dst - dstStart; *dstCharsPtr = numChars; return result; } |