summaryrefslogtreecommitdiffstats
path: root/generic/tclUtil.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclUtil.c')
-rw-r--r--generic/tclUtil.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/generic/tclUtil.c b/generic/tclUtil.c
index d542b52..76676a1 100644
--- a/generic/tclUtil.c
+++ b/generic/tclUtil.c
@@ -89,15 +89,19 @@ Tcl_ObjType tclEndOffsetType = {
/*
*----------------------------------------------------------------------
*
- * TclCountSpaceRuns --
+ * TclMaxListLength --
*
* Given 'bytes' pointing to 'numBytes' bytes, scan through them and
* count the number of whitespace runs that could be list element
* separators. If 'numBytes' is -1, scan to the terminating '\0'.
+ * Not a full list parser. Typically used to get a quick and dirty
+ * overestimate of length size in order to allocate space for an
+ * actual list parser to operate with.
*
* Results:
- * Returns the count. If 'endPtr' is not NULL, writes a pointer to
- * the end of the string scanned there.
+ * Returns the largest number of list elements that could possibly
+ * be in this string, interpreted as a Tcl list. If 'endPtr' is not
+ * NULL, writes a pointer to the end of the string scanned there.
*
* Side effects:
* None.
@@ -106,13 +110,22 @@ Tcl_ObjType tclEndOffsetType = {
*/
int
-TclCountSpaceRuns(
+TclMaxListLength(
CONST char *bytes,
int numBytes,
CONST char **endPtr)
{
int count = 0;
+ if ((numBytes == 0) || ((numBytes == -1) && (*bytes == '\0'))) {
+ /* Empty string case - quick exit */
+ goto done;
+ }
+
+ /* No list element before leading white space */
+ count += 1 - TclIsSpaceProc(*bytes);
+
+ /* Count white space runs as potential element separators */
while (numBytes) {
if ((numBytes == -1) && (*bytes == '\0')) {
break;
@@ -132,6 +145,11 @@ TclCountSpaceRuns(
bytes++;
numBytes -= (numBytes != -1);
}
+
+ /* No list element following trailing white space */
+ count -= TclIsSpaceProc(bytes[-1]);
+
+ done:
if (endPtr) {
*endPtr = bytes;
}
@@ -462,16 +480,19 @@ Tcl_SplitList(
int length, size, i, result, elSize, brace;
/*
- * Figure out how much space to allocate. There must be enough space for
- * both the array of pointers and also for a copy of the list. To estimate
- * the number of pointers needed, count the number of space characters in
- * the list.
+ * Allocate enough space to work in. A (CONST char *) for each
+ * (possible) list element plus one more for terminating NULL,
+ * plus as many bytes as in the original string value, plus one
+ * more for a terminating '\0'. Space used to hold element separating
+ * white space in the original string gets re-purposed to hold '\0'
+ * characters in the argv array.
*/
- size = TclCountSpaceRuns(list, -1, &end) + 2;
+ size = TclMaxListLength(list, -1, &end) + 1;
length = end - list;
argv = (CONST char **) ckalloc((unsigned)
((size * sizeof(char *)) + length + 1));
+
for (i = 0, p = ((char *) argv) + size*sizeof(char *);
*list != 0; i++) {
CONST char *prevList = list;