Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Tighten SetDictFromAny(). |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | core-8-5-branch |
Files: | files | file ages | folders |
SHA1: |
6a588e6fc4c0e6471cb20fbca87d25c7 |
User & Date: | dgp 2011-05-03 17:34:51 |
Context
2011-05-03
| ||
18:53 | Tighten SetListFromAny(). check-in: d711aba568 user: dgp tags: core-8-5-branch | |
17:34 | Tighten SetDictFromAny(). check-in: 6a588e6fc4 user: dgp tags: core-8-5-branch | |
2011-05-02
| ||
20:34 | Rewrite of parts of the switch compiler to better use the powers of TclFindElement() and do less par... check-in: 8bc0f9df3c user: dgp tags: core-8-5-branch | |
Changes
Changes to ChangeLog.
1 2 3 4 5 6 7 | 2011-05-02 Don Porter <[email protected]> * generic/tclCmdMZ.c: Revised TclFindElement() interface. The * generic/tclDictObj.c: final argument had been bracePtr, the address * generic/tclListObj.c: of a boolean var, where the caller can be told * generic/tclParse.c: whether or not the parsed list element was * generic/tclUtil.c: enclosed in braces. In practice, no callers | > > > > | 1 2 3 4 5 6 7 8 9 10 11 | 2011-05-03 Don Porter <[email protected]> * generic/tclDictObj.c: Tighten SetDictFromAny(). 2011-05-02 Don Porter <[email protected]> * generic/tclCmdMZ.c: Revised TclFindElement() interface. The * generic/tclDictObj.c: final argument had been bracePtr, the address * generic/tclListObj.c: of a boolean var, where the caller can be told * generic/tclParse.c: whether or not the parsed list element was * generic/tclUtil.c: enclosed in braces. In practice, no callers |
︙ | ︙ |
Changes to generic/tclDictObj.c.
︙ | ︙ | |||
552 553 554 555 556 557 558 | */ static int SetDictFromAny( Tcl_Interp *interp, Tcl_Obj *objPtr) { | | < | < < < | | > > | < < < | < | < | | < < < | < < < < | < < | < < < | < < < < < < < | | < < > | < | < < < < < | | | | | | | | | > > | < < < < < | | < | < < | | | | | < < < < | | | | | | | < < | < < < < < < < | | < | < < | | | > | | | | < < | | | | | | | | | | | | < | 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | */ static int SetDictFromAny( Tcl_Interp *interp, Tcl_Obj *objPtr) { Tcl_HashEntry *hPtr; int isNew, result; Dict *dict = (Dict *) ckalloc(sizeof(Dict)); InitChainTable(dict); /* * Since lists and dictionaries have very closely-related string * representations (i.e. the same parsing code) we can safely special-case * the conversion from lists to dictionaries. */ if (objPtr->typePtr == &tclListType) { int objc, i; Tcl_Obj **objv; /* Cannot fail, we already know the Tcl_ObjType is "list". */ TclListObjGetElements(NULL, objPtr, &objc, &objv); if (objc & 1) { goto missingValue; } for (i=0 ; i<objc ; i+=2) { /* Store key and value in the hash table we're building. */ hPtr = CreateChainEntry(dict, objv[i], &isNew); if (!isNew) { Tcl_Obj *discardedValue = Tcl_GetHashValue(hPtr); /* * Not really a well-formed dictionary as there are duplicate * keys, so better get the string rep here so that we can * convert back. */ (void) Tcl_GetString(objPtr); TclDecrRefCount(discardedValue); } Tcl_SetHashValue(hPtr, objv[i+1]); Tcl_IncrRefCount(objv[i+1]); /* Since hash now holds ref to it */ } } else { int length; const char *nextElem = TclGetStringFromObj(objPtr, &length); const char *limit = (nextElem + length); while (nextElem < limit) { Tcl_Obj *keyPtr, *valuePtr; const char *elemStart; int elemSize, literal; result = TclFindElement(interp, nextElem, (limit - nextElem), &elemStart, &nextElem, &elemSize, &literal); if (result != TCL_OK) { goto errorExit; } if (elemStart == limit) { break; } if (nextElem == limit) { goto missingValue; } if (literal) { TclNewStringObj(keyPtr, elemStart, elemSize); } else { /* Avoid double copy */ TclNewObj(keyPtr); keyPtr->bytes = ckalloc((unsigned) elemSize + 1); keyPtr->length = TclCopyAndCollapse(elemSize, elemStart, keyPtr->bytes); } result = TclFindElement(interp, nextElem, (limit - nextElem), &elemStart, &nextElem, &elemSize, &literal); if (result != TCL_OK) { TclDecrRefCount(keyPtr); goto errorExit; } if (literal) { TclNewStringObj(valuePtr, elemStart, elemSize); } else { /* Avoid double copy */ TclNewObj(valuePtr); valuePtr->bytes = ckalloc((unsigned) elemSize + 1); valuePtr->length = TclCopyAndCollapse(elemSize, elemStart, valuePtr->bytes); } /* Store key and value in the hash table we're building. */ hPtr = CreateChainEntry(dict, keyPtr, &isNew); if (!isNew) { Tcl_Obj *discardedValue = Tcl_GetHashValue(hPtr); TclDecrRefCount(keyPtr); TclDecrRefCount(discardedValue); } Tcl_SetHashValue(hPtr, valuePtr); Tcl_IncrRefCount(valuePtr); /* since hash now holds ref to it */ } } /* * Free the old internalRep before setting the new one. We do this as late * as possible to allow the conversion code, in particular * Tcl_GetStringFromObj, to use that old internalRep. */ TclFreeIntRep(objPtr); dict->epoch = 0; dict->chain = NULL; dict->refcount = 1; objPtr->internalRep.otherValuePtr = dict; objPtr->typePtr = &tclDictType; return TCL_OK; missingValue: if (interp != NULL) { Tcl_SetResult(interp, "missing value to go with key", TCL_STATIC); } result = TCL_ERROR; errorExit: DeleteChainTable(dict); ckfree((char *) dict); return result; } |
︙ | ︙ |
Changes to generic/tclUtil.c.
︙ | ︙ | |||
176 177 178 179 180 181 182 | * that's part of the element. If this is the last argument in the list, * then *nextPtr will point just after the last character in the list * (i.e., at the character at list+listLength). If sizePtr is non-NULL, * *sizePtr is filled in with the number of characters in the element. If * the element is in braces, then *elementPtr will point to the character * after the opening brace and *sizePtr will not include either of the * braces. If there isn't an element in the list, *sizePtr will be zero, | | | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | * that's part of the element. If this is the last argument in the list, * then *nextPtr will point just after the last character in the list * (i.e., at the character at list+listLength). If sizePtr is non-NULL, * *sizePtr is filled in with the number of characters in the element. If * the element is in braces, then *elementPtr will point to the character * after the opening brace and *sizePtr will not include either of the * braces. If there isn't an element in the list, *sizePtr will be zero, * and both *elementPtr and *nextPtr will point just after the last * character in the list. If literalPtr is non-NULL, *literalPtr is set * to a boolean value indicating whether the substring returned as * the values of **elementPtr and *sizePtr is the literal value of * a list element. If not, a call to TclCopyAndCollapse() is needed * to produce the actual value of the list element. Note: this function * does NOT collapse backslash sequences, but uses *literalPtr to tell * callers when it is required for them to do so. |
︙ | ︙ |