summaryrefslogtreecommitdiffstats
path: root/generic/tclEncoding.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2014-11-15 21:46:19 (GMT)
committerdgp <dgp@users.sourceforge.net>2014-11-15 21:46:19 (GMT)
commitdd3d636ee83cea5c446d72435c1bbf9e843264ec (patch)
tree856a4e1ab5f053b93224fd940ed188cc4f482e86 /generic/tclEncoding.c
parentf04588b905d72636d0d4a76b907d02a4368592eb (diff)
downloadtcl-dd3d636ee83cea5c446d72435c1bbf9e843264ec.zip
tcl-dd3d636ee83cea5c446d72435c1bbf9e843264ec.tar.gz
tcl-dd3d636ee83cea5c446d72435c1bbf9e843264ec.tar.bz2
Add to Tcl_ExternalToUtf() a capability to impose a limit on the number
of chars produce in the encoding result. When the flag TCL_ENCODING_CHAR_LIMIT is set and dstCharsPtr is not NULL, then the initial value of *dstCharsPtr is taken as the max number of chars to produce. The limit is imposed in a way that does not require the assistance of the encoding's driver procs, but the flag is passed on to them in case they can do better when they know they should. No callers updated yet. No drivers updated yet. One difficulty is that this necessarily imposes a pre-translation limit, and the I/O system has a history of wanting to impose only a post-translation limit.
Diffstat (limited to 'generic/tclEncoding.c')
-rw-r--r--generic/tclEncoding.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c
index 0446816..f33e0e6 100644
--- a/generic/tclEncoding.c
+++ b/generic/tclEncoding.c
@@ -1203,8 +1203,10 @@ Tcl_ExternalToUtf(
* output buffer. */
{
const Encoding *encodingPtr;
- int result, srcRead, dstWrote, dstChars;
+ int result, srcRead, dstWrote, dstChars = 0;
int noTerminate = flags & TCL_ENCODING_NO_TERMINATE;
+ int charLimited = (flags & TCL_ENCODING_CHAR_LIMIT) && dstCharsPtr;
+ int maxChars = INT_MAX;
Tcl_EncodingState state;
if (encoding == NULL) {
@@ -1229,6 +1231,9 @@ Tcl_ExternalToUtf(
}
if (dstCharsPtr == NULL) {
dstCharsPtr = &dstChars;
+ flags &= ~TCL_ENCODING_CHAR_LIMIT;
+ } else if (charLimited) {
+ maxChars = *dstCharsPtr;
}
if (!noTerminate) {
@@ -1241,9 +1246,20 @@ Tcl_ExternalToUtf(
dstLen--;
}
- result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen,
- flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr,
- dstCharsPtr);
+ do {
+ int savedFlags = flags;
+ Tcl_EncodingState savedState = *statePtr;
+
+ result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen,
+ flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr,
+ dstCharsPtr);
+ if (*dstCharsPtr <= maxChars) {
+ break;
+ }
+ dstLen = Tcl_UtfAtIndex(dst, maxChars) - 1 - dst + TCL_UTF_MAX;
+ flags = savedFlags;
+ *statePtr = savedState;
+ } while (1);
if (!noTerminate) {
/* ...and then append it */